当我运行以下 Python3 代码时,
def f():
x = 'foo'
def g():
return x
def h(y):
nonlocal x
x = y
return g, h
g, h = f()
print(g())
h('bar')
print(g())
我明白了
foo
bar
我曾相信在 Python 中,所有局部变量本质上都是指针。所以在我看来,x
是调用 f()
时在堆栈上分配的指针,所以当 f()
退出时,变量x
应该死了。由于字符串 'foo'
是在堆上分配的,所以当 g()
被调用时,我想“好吧,我猜 g()
还保留了指向 'foo'
的指针的副本”。但随后我可以调用 h('bar')
,g()
返回的值得到了更新。
变量 x
在哪里?我的 Python 局部变量模型全错了吗?
编辑:
@chepner 在评论中几乎回答了我的问题。在一个地方他说局部变量存储在一个类似字典的对象中,然后在另一个地方他链接了https://docs.python.org/3.4/reference/executionmodel.html#naming-and-binding。 , 以支持他的主张。
此时我很高兴。如果 chepner 要写一个重复他的评论的答案,我会接受它作为最佳答案。否则,请考虑此问题已解决。
最佳答案
@chepner 很久以前就在评论中回答了我的问题。
如果@chepner 发布了一个答案,我会接受他的回答。但已经快一年了,我认为现在我自己发布答案并接受它是公平的。
我最初问这个问题是因为我不明白Python中堆栈帧中存储的是什么。
在 Java 中,如果您的代码如下所示:
void f() {
Integer x = 1;
Integer y = 2;
}
在栈上为两个指针分配了内存。
然而,在 Python 中,如果你有这样的代码
def f():
x = 1
y = 2
堆栈上没有分配额外的内存。
在伪C++中,上面的python代码更类似于
void f() {
PythonDict * scope = MakePythonDict();
scope->set("x", MakeInt(1));
scope->set("y", MakeInt(2));
}
所以对于我最初的问题,变量 x
保持事件状态,因为它存在于 scope
指向的字典中,它在闭包中传递。
请注意,当函数退出时,scope
指针仍然会消失。
关于python - 局部变量如何与 Python 闭包一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25023076/