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

34 python closures python-internals

Beazley第100页提到:

>>>python.__closure__
(<cell at 0x67f50: str object at 0x69230>,)
>>>python.__closure__[0].cell_contents
Run Code Online (Sandbox Code Playgroud)

我的理解是这__closure__是一个列表但是这些单元格和str对象是什么?这看起来像一个单元组?

Mar*_*ers 43

闭包单元指的是函数所需的值,但是取自周围的范围.

当Python编译一个嵌套函数,它指出它引用但仅在两个嵌套函数和父范围的代码对象父功能(未全局)中所定义的任何变量.这些是这些函数的对象的属性co_freevarsco_cellvars属性__code__.

然后,当您实际创建嵌套函数(在执行父函数时发生)时,这些引用随后用于将闭包附加到嵌套函数.

函数闭包持有一个单元格元组,每个自由变量一个(命名为co_freevars); cells是对父作用域的局部变量的特殊引用,它遵循这些局部变量指向的值.最好用一个例子来说明:

def foo():
    def bar():
        print(spam)

    spam = 'ham'
    bar()
    spam = 'eggs'
    bar()
    return bar

b = foo()
b()
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,函数bar有一个闭包单元,它指向spam函数foo.细胞遵循的价值spam.更重要的是,一旦foo()完成并bar返回,eggs即使spam内部变量foo不再存在,单元格仍继续引用值(字符串).

因此,上面的代码输出:

>>> b=foo()
ham
eggs
>>> b()
eggs
Run Code Online (Sandbox Code Playgroud)

并且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()
Run Code Online (Sandbox Code Playgroud)

上面将salad连续打印三次,因为所有三个lambda函数都引用spam变量,而不是创建函数对象时绑定的值.当for循环结束时,spam被绑定'salad',因此所有三个闭包都将解析为该值.

  • 仅供参考,“__closure__”中元素的顺序是任意的(哈希表有序)。如果要将自由变量的名称与其值相匹配,请使用“__code__.co_freevars”和“__closure__[&lt;index&gt;].cell_contents”的组合。第一个的索引“i”“co_freevars”对应于“__closure__”的索引“i”。 (6认同)
  • @IllyaGerasymchuk:或者,只需使用 [`inspect.getclosurevars()` 函数](https://docs.python.org/3/library/inspect.html#inspect.getclosurevars),它会为您组合名称。 (2认同)

ATO*_*TOA 7

它是旧的Python 3新名称func_closure.

http://docs.python.org/3.0/whatsnew/3.0.html

func_X已重命名named的函数属性以使用该__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包含函数自由变量绑定的单元格.

此外,它不可写.

参考: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]
Run Code Online (Sandbox Code Playgroud)

输出:

>>> 
['I am free', 'I am free too']
Run Code Online (Sandbox Code Playgroud)

正如foo返回bar使用自己的值的函数x,但不是yz.所以,他们来了__closure__.