Beazley pg 100 提到:
>>>python.__closure__
(<cell at 0x67f50: str object at 0x69230>,)
>>>python.__closure__[0].cell_contents
我的理解是这__closure__是一个列表,但是这些单元格的东西和 str 对象是什么?这看起来像一个一元元组?
Beazley pg 100 提到:
>>>python.__closure__
(<cell at 0x67f50: str object at 0x69230>,)
>>>python.__closure__[0].cell_contents
我的理解是这__closure__是一个列表,但是这些单元格的东西和 str 对象是什么?这看起来像一个一元元组?
闭包单元指的是函数所需的值,但取自周围的范围。
当 Python 编译嵌套函数时,它会记下它引用但仅在嵌套函数和父范围的代码对象中的父函数(不是全局变量)中定义的任何变量。这些分别是这些函数对象的co_freevars和co_cellvars属性。__code__
然后,当您实际创建嵌套函数(执行父函数时发生)时,这些引用将用于将闭包附加到嵌套函数。
函数闭包包含一个单元元组,每个单元对应一个自由变量(在 中命名co_freevars);单元格是对父作用域的局部变量的特殊引用,它遵循那些局部变量指向的值。最好用一个例子来说明这一点:
def foo():
def bar():
print(spam)
spam = 'ham'
bar()
spam = 'eggs'
bar()
return bar
b = foo()
b()
在上面的例子中,函数bar有一个闭包单元,它指向spam函数中的foo。单元格遵循 的值spam。更重要的是,一旦foo()完成并返回,即使里面的变量不再存在bar,单元格也会继续引用该值(字符串)。eggsspamfoo
因此,上面的代码输出:
>>> 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',因此所有三个闭包都将解析为该值。
它是旧的 Python 3 的新名称func_closure。
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分别重命名为__closure__,__code__,__defaults__,__dict__,__doc__,__globals__,__name__。
简而言之:
__closure__isNone或 atuple包含对函数的自由变量的绑定的单元格。
此外,它不可写。
参考: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]
输出:
>>>
['I am free', 'I am free too']
就像foo返回bar使用自己的值的函数一样x,但不是yor z。所以,他们归于__closure__.
当closure在 python 中定义嵌套函数()时:
外部函数用于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
()
>>> 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
我从未见过其他地方使用过的细胞类型。它似乎是专门为保存闭包变量而设计的。