LOAD_DEREF(i)
Loads the cell contained in slot i of the cell and free variable storage. Pushes a reference to the object the cell contains on the stack.
STORE_DEREF(i)¶
Stores TOS into the cell contained in slot i of the cell and free variable storage.
dis 写道
LOAD_CLOSURE(i)
Pushes a reference to the cell contained in slot i of the cell and free variable storage. The name of the variable is co_cellvars if i is less than the length of co_cellvars. Otherwise it is co_freevars[i - len(co_cellvars)].
dis 写道
MAKE_CLOSURE(argc)
Creates a new function object, sets its func_closure slot, and pushes it on the stack. TOS is the code associated with the function, TOS1 the tuple containing cells for the closure’s free variables. The function also has argc default parameters, which are found below the cells.
def foo():
a = 1
def bar():
b = a + 1
return bar
b = foo()
print 'bar func_closure:', b.func_closure
如果这程序按照猜测的结果运行,那么将会返回一个cell的tuple。执行结果如下。
bar func_closure: (<cell at 0x454690: int object at 0x803388>,)
果然不出所料。那么func_closure的作用在文档里面怎么描述呢?
datamodel 写道
func_closureNone or a tuple of cells that contain bindings for the function’s free variables.Read-only
看来这个东东涉及到的是Python的名字查找顺序的问题。先local,再闭包,再global。
详细内容可以参看PEP227里面有这么一句话。
PEP227 写道
The implementation adds several new opcodes and two new kinds of
names in code objects. A variable can be either a cell variable
or a free variable for a particular code object. A cell variable
is referenced by containing scopes; as a result, the function
where it is defined must allocate separate storage for it on each
invocation. A free variable is referenced via a function's
closure.
The choice of free closures was made based on three factors.
First, nested functions are presumed to be used infrequently,
deeply nested (several levels of nesting) still less frequently.
Second, lookup of names in a nested scope should be fast.
Third, the use of nested scopes, particularly where a function
that access an enclosing scope is returned, should not prevent
unreferenced objects from being reclaimed by the garbage
collector.
相信看到前面func_closure是readonly,大家一定非常失望。看看别的语言的实现如何。
javascript的版本1。
function foo(){
var num = 1;
function bar(){
var num = num + 1;
alert(num);
}
bar()
}
foo();
这个版本会报NaN。。说明Python的问题Javascipt也有。
那如果说num不声明为var呢?
function foo(){
var num = 1;
function bar(){
num = num + 1;
alert(num);
}
bar()
}
foo();
正确提示2.。
要是Python也有这样的机制好了。。
令人高兴的是,python3里面终于改观了。从语法到底层全都支持了(貌似是一个性质)。
语法上加上了nonlocal关键字。
def foo():
a = 1
def bar():
nonlocal a
a = a + 1
print(a)
return bar
foo()()
正确返回2!!
底层加上了可爱的下面两个函数。
PyObject* PyFunction_GetClosure(PyObject *op)¶
Return value: Borrowed reference.
Return the closure associated with the function object op. This can be NULL or a tuple of cell objects.
int PyFunction_SetClosure(PyObject *op, PyObject *closure)
Set the closure associated with the function object op. closure must be Py_None or a tuple of cell objects.
Raises SystemError and returns -1 on failure.