Python中的变量/函数捕获背后的机制是什么?

时间:2018-08-03 08:25:23

标签: python

我正在尝试生成一些依赖于变量的函数f并将它们存储在列表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在这种情况下如何捕获变量或函数缺乏深入的了解。有人可以解释这种行为背后的原因吗?还有一种更直接的方法来实现我最初想要做的事情吗?

1 个答案:

答案 0 :(得分:-1)

问题在于变量绑定,因为它们在全局范围内引用了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()

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