首页 > 解决方案 > python中变量/函数捕获背后的机制是什么?

问题描述

我正在尝试生成许多f依赖于变量的函数并将它们存储到 list 中fs

我第一次尝试

fs = []
for v in range(3):
  def f():
    print(v)
  fs.append(f)

for f in fs:
  f()

但这输出

2
2
2

即只调用最后一个函数。

我认为这可能是因为该函数f在每个循环中都会被覆盖,但后来我尝试了

fs = []
for v in range(3):
  def f():
    print(v)
  fs.append(f)
  def f():
    print('foo')
  fs.append(f)

for f in fs:
  f()

哪个输出

2
foo
2
foo
2
foo

所以看起来python至少能够区分这两个同名的函数。

然后我虽然我会动态创建f

fs = []
for v in range(3):
  def make_f():
    def f():
      print(v)
    return f
  fs.append(make_f())

for f in fs:
  f()

但这仍然输出

2
2
2

最后,我对make_v工厂进行了参数化,最终得到了我想要的结果:

fs = []
for v in range(3):
  def make_f(v):
    def f():
      print(v)
    return f
  fs.append(make_f(v))

for f in fs:
  f()

印刷

0
1
2

尽管我最终破解了一个解决方案,但我认为我对 python 如何在这些情况下捕获变量或函数确实缺乏一些更深入的了解。有人可以解释这种行为背后的理由吗?有没有更直接的方法来实现我最初想做的事情?

标签: python

解决方案


问题是变量绑定,因为它们v在全局范围内引用,最后是 2。您可以通过将变量绑定到本地范围来解决此问题。

fs = []
for v in range(3):
  def make_f(v=v):
    def f():
      print(v)
    return f
  fs.append(make_f())

for f in fs:
  f()

希望这有助于您进一步了解正在发生的事情。


推荐阅读