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

标签 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' 的指针的副本”。但随后我可以调用 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/

相关文章:

python - 比较两个列表的元素

python - 如何在 networkx 中创建连通图

python-3.x - 获取 Azure ML 环境构建状态

closures - 如何在 swift 中使用 completionBlock?

swift - 为什么我在第二个例子中得到保留圈?

python - 在 Python 中调用 MySQL 存储过程 - 参数错误 # 不正确

python - Google 风格指南中的可选类型提示

python - 我可以将变量标记为 transient 以便它们不会被 pickle 吗?

python - 使用另一个 python 文件中的变量

javascript - 在未来事件中使用闭包的问题