如何从函数的闭包中访问/修改变量?

6
如果我有一个包含一些非本地变量(在闭包中)的函数,我该如何访问这些变量?我能修改它吗?如果可以,应该怎么做?下面是一个这样的函数例子:
def outer():
    x = 1
    def inner(y):
        nonlocal x
        return x + y
    return inner

inner = outer()
# how do I get / change the value of x inside inner?

(如果此问题已在其他地方得到回答,我很抱歉;我找不到它,所以一旦我解决了它,我就想分享答案)
1个回答

8

一个函数的封闭变量被存储为元组,存储在__closure__属性中。这些变量以cell类型存储,看起来只是一个可变容器,用于存储变量本身。您可以通过cell.cell_contents访问cell存储的变量。由于cell是可变的,因此可以通过改变单元格内容来更改函数的非局部变量的值。以下是一个示例:

def outer():
    x = 1
    def inner(y):
        nonlocal x
        return x + y
    return inner

inner = outer()

print(inner(2))  # 3
print(inner.__closure__)  # (<cell at 0x7f14356caf78: int object at 0x56487ab30380>,)
print(inner.__closure__[0].cell_contents)  # 1

inner.__closure__[0].cell_contents = 10
print(inner(2))  # 12
print(inner.__closure__[0].cell_contents)  # 10

编辑 - 上面的答案适用于Python 3.7+。对于其他版本的Python,您可以以同样的方式访问闭包,但是您无法修改封闭变量(这里是跟踪设置单元格值的Python问题)。


1
我在使用CPython 3.6.7时出现了AttributeError:attribute 'cell_contents' of 'cell' objects is not writable的错误。而在pypy 6中,我得到了AttributeError:readonly attribute 'cell_contents'的错误消息。你使用的Python版本允许写入cell_contents吗?或者我需要配置一些东西才能使其工作? - Ray Toal
啊,我没有检查其他版本;当我运行时,我正在使用3.7。我现在会更新。 - Nathan
1
备注:我相信可以通过名称访问x,请参考closures - Reflect / Inspect closed-over variables in Python - Stack Overflow - user202729

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接