python闭包异常行为

python闭包异常行为,python,closures,lexical-closures,Python,Closures,Lexical Closures,我正在尝试中的问题中的一段代码 输出为: None None None 不是吗 (<cell at 0x9222d94: int object at 0x8cabdbc>,) (<cell at 0x9222d94: int object at 0x8cabdbc>,) (<cell at 0x9222d94: int object at 0x8cabdbc>,) 我正在使用Python 2.6.6(r266:84292,2010年9月15日,15:52:

我正在尝试中的问题中的一段代码

输出为:

None
None
None
不是吗

(<cell at 0x9222d94: int object at 0x8cabdbc>,)
(<cell at 0x9222d94: int object at 0x8cabdbc>,)
(<cell at 0x9222d94: int object at 0x8cabdbc>,)
我正在使用Python 2.6.6(r266:84292,2010年9月15日,15:52:39)。

指定
func_闭包
为“无或包含函数自由变量绑定的单元格元组”

现在,请注意两个版本之间的差异:在第一个版本中,
i
是一个模块级(即全局)变量。每个功能的评估结果相同:

>>> [f(2) for f in flist]
[4, 4, 4]
在每个函数中,
i
不是自由的,而是指全局的
i
,因此不,输出不应该是非零长度元组的列表


实际上,您可能并不关心
func_闭包的值,除非您正在做一些相当深的魔术。如果您正在做一些神奇的事情,请注意,给定规范,如果没有自由变量,
func_closure
不应该是空元组似乎没有充分的理由,因此,如果您希望代码在python的不同点版本之间可移植,请适当地处理这种情况。

只有在全局(模块)范围外引用变量时,才会引入闭包:

只有当内部函数引用周围范围中的变量时,才会生成闭包:

>>> 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>,)

在第一个示例中,
i
是一个模块作用域变量,只有在第二个示例中,才通过将代码包装到新函数
actualFact
来引入新作用域,这是一种不需要闭包的廉价方法

for i in xrange(3):
    def func(x, i=i): return x*i
    flist.append(func)

事实上,要做到这一点,唯一的方法是不关闭。答案已经在相关问题中了。我建议你参考它,这样人们就可以有一个更完整的清单,具体的问题。我不会给你打分,因为你没有回答我的问题。这只是故事的一部分:这是解释,因为示例中的
I
是全局的。这就是我所说的:“只有在全局(模块)范围外引用变量时,才会引入闭包”。是的,但是在OP的代码中,您没有识别任何全局变量;事实上,你并没有真正参与到OP的代码中,或者这是如何应用于它的。仅仅因为你的解释是正确的,并不意味着它是完整的。@Marcin:OP问了一个关于闭包的理论性问题,而不是他的代码示例的具体修复。尽管如此,我还是更新了我的答案。很明显,他想知道为什么他的代码没有按照他期望的那样运行。在我看来,当
func_closure
为None时,语言引用可以使用一个解释。@MartijnPieters我认为,只要没有要存储的绑定,它就是
None
。然而,这也让实现者可以自由地提供空元组。检查函数闭包的安全方法是取其布尔值。
>>> 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>,)
>>> def foo():
...     spam = 'eggs'
...     def bar(): pass
...     return bar
...
>>> foo().func_closure is None
True
for i in xrange(3):
    def func(x, i=i): return x*i
    flist.append(func)