我正在尝试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
输出结果为:
None
None
None
不应该吗?:
(<cell at 0x9222d94: int object at 0x8cabdbc>,)
(<cell at 0x9222d94: int object at 0x8cabdbc>,)
(<cell at 0x9222d94: int object at 0x8cabdbc>,)
我使用以下代码获得了上述输出:
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
我使用的是Python 2.6.6(r266:84292,2010年9月15日,15:52:39)。
答案 0 :(得分:4)
只有在全局(模块)范围之外引用变量时才会引入闭包:
>>> def foo():
... def bar(): pass
... return bar
...
>>> foo().func_closure is None
True
>>> spam = 'eggs'
>>> def foo():
... def bar(): return spam
... return bar
...
>>> foo().func_closure is None
True
只有当内部函数引用周围范围内的变量时才会生成闭包:
>>> def foo():
... spam = 'eggs'
... def bar(): return spam
... return bar
...
>>> foo().func_closure is None
False
>>> foo().func_closure
(<cell at 0x108472718: str object at 0x108471de0>,)
请注意,您实际上必须引用周围范围中的变量。只需忽略范围,您就会再次None
:
>>> def foo():
... spam = 'eggs'
... def bar(): pass
... return bar
...
>>> foo().func_closure is None
True
在第一个示例中,i
是模块范围变量,仅在第二个示例中,通过将代码包装在新函数actualFact
中来引入新范围。
答案 1 :(得分:2)
language reference指定func_closure
是&#34;无或包含函数自由变量绑定的单元格元组。&#34;
现在,请注意两个版本之间的区别:第一个版本i
是模块级(即全局)变量。评估每个函数的结果是相同的:
>>> [f(2) for f in flist]
[4, 4, 4]
在每个函数中,i
不是空闲的,而是指全局i
,所以不,输出不应该是非零长度元组的列表。
在实践中,你可能不关心func_closure
的价值,除非你做了一些相当深刻的魔术。如果你正在做一些神奇的事情,请注意,根据规范,如果没有自由变量,func_closure
不应该是一个空元组似乎没有充分的理由,所以如果你想要你的代码,请适当处理这种情况甚至可以在python的不同点版本之间移植。
答案 2 :(得分:1)
没有关闭的廉价方法
for i in xrange(3):
def func(x, i=i): return x*i
flist.append(func)