局部变量如何与Python闭包一起使用?

时间:2014-07-29 19:05:57

标签: python python-3.x closures

当我运行以下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'的指针的副本以及#34;。但是我可以调用h('bar')g()返回的值得到更新。

变量x在哪里生活?我在Python中的局部变量模型是否都错了?

编辑:

@chepner在评论中几乎回答了我的问题。在那里,他说局部变量存储在类似dict的对象中,然后是另一个链接https://docs.python.org/3.4/reference/executionmodel.html#naming-and-binding,以支持他的主张。

此时我很开心。如果chepner要写一个回答他的评论,我会接受它作为最佳答案。否则,请考虑解决此问题。

1 个答案:

答案 0 :(得分:0)

@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指向的dict中,并在闭包中传递。

请注意,当函数退出时,scope指针仍然会死。