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
,单元格也会继续引用该值(字符串)。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'
,因此所有三个闭包都将解析为该值。
它是旧的 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
,但不是y
or 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
我从未见过其他地方使用过的细胞类型。它似乎是专门为保存闭包变量而设计的。