Beazley在第100页提到:
>>>python.__closure__
(<cell at 0x67f50: str object at 0x69230>,)
>>>python.__closure__[0].cell_contents
我理解的是__closure__
是一个列表,但这些cell和str对象是什么?它看起来像是一个一元元组?
Beazley在第100页提到:
>>>python.__closure__
(<cell at 0x67f50: str object at 0x69230>,)
>>>python.__closure__[0].cell_contents
我理解的是__closure__
是一个列表,但这些cell和str对象是什么?它看起来像是一个一元元组?
闭包单元是指函数所需的值,但这些值来自其周围的范围。
当Python编译嵌套函数时,它记录在代码对象中嵌套函数和父作用域的co_freevars
和co_cellvars
属性,在父函数中引用但仅在父函数(而不是全局)中定义的任何变量。随后,当您实际创建嵌套函数(在执行父函数时发生),这些引用便被用于将一个闭包附加到嵌套函数上。
函数闭包持有一个元组,每个自由变量都有一个单元格(在co_freevars
中命名);单元格是对父作用域的本地变量的特殊引用,跟随这些本地变量所指向的值。以下是最好的示例说明:
def foo():
def bar():
print(spam)
spam = 'ham'
bar()
spam = 'eggs'
bar()
return bar
b = foo()
b()
在上述示例中,函数bar
有一个闭包单元,它指向函数foo
中的spam
。该单元跟随spam
的值。更重要的是,一旦foo()
完成并返回bar
,该单元将继续引用该值(即字符串eggs
),即使在foo
内部变量spam
不再存在。
因此,上述代码输出:
>>> 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'
,因此所有三个闭包都将解析为该值。
__closure__
中元素的顺序是任意的(按哈希表排序)。如果你想将自由变量的名称与其值匹配,请结合使用 __code__.co_freevars
和 __closure__[<index>].cell_contents
。第一个的 co_freevars
的第 i
个对应于 __closure__
的第 i
个索引。 - Illya Gerasymchukinspect.getclosurevars()
函数,该函数会为你合并名称。具体请参考:https://docs.python.org/3/library/inspect.html#inspect.getclosurevars - Martijn Pieters(读作:i prime)。这个prime是打错了吗?它应该是code.co_freevars [i]对应于__closure__ [i]吗?此外,以下链接提到了
closure,
cell_content和
cell`:https://docs.python.org/3/reference/datamodel.html#the-standard-type-hierarchy - josevillei
来标记该字符串为代码。作为管理员,我有权更正评论,所以我已经更正了。 - Martijn Pietersfunc_closure
的Python 3新名称。
http://docs.python.org/3.0/whatsnew/3.0.html
命名为__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
。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
。因此,它们属于 __closure__
。
__closure__
和cell contents的信息可以在这里找到:https://docs.python.org/3/reference/datamodel.html#the-standard-type-hierarchy - joseville 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
我从未在其他地方看到过使用 cell 类型。它似乎是专门用来保存闭包变量的。