python - 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 如何在这些情况下捕获变量或函数确实缺乏一些更深入的了解。有人可以解释这种行为背后的理由吗?有没有更直接的方法来实现我最初想做的事情?
解决方案
问题是变量绑定,因为它们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()
希望这有助于您进一步了解正在发生的事情。
推荐阅读
- html - 如何将图像绑定到作为 vue.js 中后端响应的图像部分?
- java - 将列表分解为单个列表 java
- html - 大文件上传问题(在本地工作但不在服务器上工作)
- java - 监听器内部的变量不会改变
- airflow - 气流 log_format 使用 logging_mixin.py 作为源文件而不是真正的源文件
- c++ - 如果我向这样的向量提供输入,这有什么问题?
- python - leetcode 中的斐波那契
- python - 如何计算熊猫列表中每个字符串的唯一计数?
- python - Django 表单 - 具有数字范围的 ChoiceField
- python - 扩展节点。在这种情况下它是如何工作的?