obj .__ closure__中究竟包含了什么?

时间:2013-01-19 11:41:21

标签: python closures python-internals

Beazley pg 100提到:

>>>python.__closure__
(<cell at 0x67f50: str object at 0x69230>,)
>>>python.__closure__[0].cell_contents

我的理解是__closure__是一个列表,但这就是全部 单元格和str对象??这看起来像一个一元组的元组?

4 个答案:

答案 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_closurefunc_codefunc_defaultsfunc_dictfunc_docfunc_globalsfunc_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而不是barx的函数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
()