I am trying a piece of code from the question in Lexical closures in Python
flist = []
for i in xrange(3):
def func(x): return x*i
flist.append(func)
for f in flist:
print f.func_closure
The output is:
None
None
None
Shouldn't it be?:
(<cell at 0x9222d94: int object at 0x8cabdbc>,)
(<cell at 0x9222d94: int object at 0x8cabdbc>,)
(<cell at 0x9222d94: int object at 0x8cabdbc>,)
I have got the above output using the following code:
flist = []
def actualFact():
for i in xrange(3):
def func(x): return x * i
flist.append(func)
for f in flist:
print f.func_closure
I am using Python 2.6.6 (r266:84292, Sep 15 2010, 15:52:39).
A cheap way to do this without a closure
Closures are only introduced if there are variables to be referenced outside of the global (module) scope:
Only when the inner function refers to a variable in the surrounding scope are closures generated:
Note that you actually have to refer to a variable in the surrounding scope. Simply ignoring the scope gives you
None
again:In your first example,
i
is a module-scope variable, only in your second example do you introduce a new scope by wrapping the code in a new functionactualFact
.The language reference specifies that
func_closure
is "None or a tuple of cells that contain bindings for the function’s free variables."Now, note the difference between your two versions: in the first version
i
is a module-level (i.e. global) variable. The result of evaluating each of the functions is the same:In each function,
i
is not free, but refers to the globali
, so no, the output should not be a list of non-zero-length tuples.In practice, you probably don't care about the value of
func_closure
, unless you're doing some fairly deep magic. If you are doing something magic, note that given the specification, there seems to be no good reason whyfunc_closure
should not be an empty tuple if there are no free variables, so handle that case appropriately if you want your code to be portable between even different point-versions of python.