一个obj.闭包里到底包含了什么?

2024-03-29 00:27:17 发布

您现在位置:Python中文网/ 问答频道 /正文

比兹利第100页提到:

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

我的理解是__closure__是一个列表,但这是什么 细胞物质和str物体??看起来像一元元组?


Tags: 列表objectcontentscellat物体细胞元组
3条回答

闭包单元格指的是函数所需的值,但这些值取自周围的范围。

当Python编译嵌套函数时,它会注意到它引用的任何变量,但这些变量仅在嵌套函数和父作用域的代码对象中的父函数(而不是全局)中定义。这些分别是这些函数的__code__对象上的co_freevarsco_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,即使foo中的变量spam不再存在,单元格仍继续引用该值(字符串eggs)。

因此,上述代码输出:

>>> 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',因此所有三个闭包都将解析为该值。

它是旧的func_closure的新Python 3名称。

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

The function attributes named func_X have been renamed to use the __X__ form, freeing up these names in the function attribute namespace for user-defined attributes. To wit, func_closure, func_code, func_defaults, func_dict, func_doc, func_globals, func_name were renamed to __closure__, __code__, __defaults__, __dict__, __doc__, __globals__, __name__, respectively.

简而言之:

__closure__是包含函数自由变量绑定的Nonetuple细胞。

而且,它是不可写的。

引用: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,而不是yz。所以,它们属于__closure__

>>> 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

我从未见过在其他地方使用的单元格类型。它似乎是专门为保存闭包变量而构建的。

相关问题 更多 >