Beazley pg 100提到:
>>>python.__closure__
(<cell at 0x67f50: str object at 0x69230>,)
>>>python.__closure__[0].cell_contents
我的理解是__closure__
是一个列表,但这就是全部
单元格和str对象??这看起来像一个一元组的元组?
答案 0 :(得分:37)
闭包单元指的是函数所需的值,但是取自周围的范围。
当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()
在上面的示例中,函数bar
有一个闭包单元格,它指向函数spam
中的foo
。该单元格遵循spam
的值。更重要的是,一旦foo()
完成并返回bar
,即使eggs
内的变量spam
,单元格仍继续引用该值(字符串foo
)不再存在。
因此,上面的代码输出:
>>> b=foo()
ham
eggs
>>> b()
eggs
且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()
以上将连续三次打印salad
,因为所有三个lambda
函数都引用spam
变量,而不是创建函数对象时绑定的值。当for
循环结束时,spam
绑定到'salad'
,因此所有三个闭包都将解析为该值。
答案 1 :(得分:5)
这是旧版func_closure
的新Python 3名称。
http://docs.python.org/3.0/whatsnew/3.0.html
名为
func_X
的函数属性已重命名为使用__X__
表单,在函数属性名称空间中为用户定义的属性释放这些名称。也就是说,func_closure
,func_code
,func_defaults
,func_dict
,func_doc
,func_globals
,func_name
已重命名为{{1}分别是{},__closure__
,__code__
,__defaults__
,__dict__
,__doc__
,__globals__
。
简而言之:
__name__
是__closure__
或None
个包含函数自由变量绑定的单元格。
此外,它不可写。
参考:http://docs.python.org/ref/types.html
示例 Python&lt; 3(所以我使用tuple
)
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]
当>>>
['I am free', 'I am free too']
返回使用自己的值foo
而不是bar
或x
的函数y
。所以,它们属于z
。
答案 2 :(得分:1)
>>> def f():
... a = "HELO"
... b = 1.0
... def w(c):
... return a,b,c
... return w
>>> w = f()
>>> w.__closure__
(<cell at 0xa05c4ac: str object at 0x9e91b74>, <cell at 0xa05c3bc: float object at 0xb733dde8>)
>>> w.__closure__[0].cell_contents
'HELO'
>>> w.__closure__[1].cell_contents
1.0
我从未见过其他地方使用的单元格类型。它似乎是专门用于保存闭包变量。
答案 3 :(得分:0)
在python中定义嵌套函数(closure
)时:
外部函数使用co_cellvars
来记录外部函数中定义的变量,这些变量可以由内部函数引用
内部函数使用co_freevars
来记录外部函数中定义的变量,可供以后使用。
示例:
# python3
Python 3.4.5 (default, May 29 2017, 15:17:55)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-11)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def foo(n):
... a = 1
... def g(n):
... return a - n
... return g
...
>>> foo.__closure__
>>> foo.__code__.co_freevars
()
>>> foo.__code__.co_cellvars
('a',)
>>> foo(0).__closure__
(<cell at 0x7f2cd98db1c8: int object at 0x7f2cd9847960>,)
>>> foo(0).__closure__[0].cell_contents
1
>>> foo(0).__code__.co_freevars
('a',)
>>> foo(0).__code__.co_cellvars
()