34 python closures python-internals
Beazley第100页提到:
>>>python.__closure__
(<cell at 0x67f50: str object at 0x69230>,)
>>>python.__closure__[0].cell_contents
Run Code Online (Sandbox Code Playgroud)
我的理解是这__closure__是一个列表但是这些单元格和str对象是什么?这看起来像一个单元组?
Mar*_*ers 43
闭包单元指的是函数所需的值,但是取自周围的范围.
当Python编译一个嵌套函数,它指出它引用但仅在两个嵌套函数和父范围的代码对象父功能(未全局)中所定义的任何变量.这些是这些函数的对象的属性co_freevars和co_cellvars属性__code__.
然后,当您实际创建嵌套函数(在执行父函数时发生)时,这些引用随后用于将闭包附加到嵌套函数.
函数闭包持有一个单元格元组,每个自由变量一个(命名为co_freevars); cells是对父作用域的局部变量的特殊引用,它遵循这些局部变量指向的值.最好用一个例子来说明:
def foo():
def bar():
print(spam)
spam = 'ham'
bar()
spam = 'eggs'
bar()
return bar
b = foo()
b()
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,函数bar有一个闭包单元,它指向spam函数foo.细胞遵循的价值spam.更重要的是,一旦foo()完成并bar返回,eggs即使spam内部变量foo不再存在,单元格仍继续引用值(字符串).
因此,上面的代码输出:
>>> b=foo()
ham
eggs
>>> b()
eggs
Run Code Online (Sandbox Code Playgroud)
并且b.__closure__[0].cell_contents是'eggs'.
注意,在调用时bar(),闭包被取消引用; 闭包不会捕获这里的值.当您生成引用循环变量的嵌套函数(带有lambda表达式或def语句)时,这会有所不同:
def foo():
bar = []
for spam in ('ham', 'eggs', 'salad'):
bar.append(lambda: spam)
return bar
for bar in foo():
print bar()
Run Code Online (Sandbox Code Playgroud)
上面将salad连续打印三次,因为所有三个lambda函数都引用spam变量,而不是创建函数对象时绑定的值.当for循环结束时,spam被绑定'salad',因此所有三个闭包都将解析为该值.
它是旧的Python 3新名称func_closure.
http://docs.python.org/3.0/whatsnew/3.0.html
func_X已重命名named的函数属性以使用该__X__表单,从而在函数属性名称空间中释放这些名称以用于用户定义的属性.要机智,func_closure,func_code,func_defaults,func_dict,func_doc,func_globals,func_name已更名为__closure__,__code__,__defaults__,__dict__,__doc__,__globals__,__name__,分别.
简而言之:
__closure__是None一个或一个tuple包含函数自由变量绑定的单元格.
此外,它不可写.
参考:http://docs.python.org/ref/types.html
示例 Python <3(所以我正在使用func_closure)
def foo():
x = "I am used"
y = "I am free"
z = "I am free too"
def bar(x):
return x, y, z
return bar
c = foo().func_closure
print [i.cell_contents for i in c]
Run Code Online (Sandbox Code Playgroud)
输出:
>>>
['I am free', 'I am free too']
Run Code Online (Sandbox Code Playgroud)
正如foo返回bar使用自己的值的函数x,但不是y或z.所以,他们来了__closure__.