quo*_*tor 20 python closures for-loop
我刚刚遇到了Eric Lippert关于通过SO 认为有害的循环变量的Closing,并且在经过实验之后,意识到在Python中存在同样的问题(并且更难以绕过).
>>> l = []
>>> for r in range(10):
... def foo():
... return r
... l.append(foo)
...
>>> for f in l:
... f()
...
9
9
9
# etc
Run Code Online (Sandbox Code Playgroud)
并且,标准的C#解决方法不起作用(我假设因为Python中引用的性质)
>>> l = []
>>> for r in range(10):
... r2 = r
... def foo():
... return r2
... l.append(foo)
...
>>> for f in l:
... f()
...
9
9
9
# etc
Run Code Online (Sandbox Code Playgroud)
我认识到这在Python中并不是一个问题,它一般强调非闭包对象结构,但我很好奇是否有一种明显的Pythonic方法来处理这个问题,或者我们是否必须采用JS的路径嵌套函数调用实际创建新变量?
>>> l = []
>>> for r in range(10):
... l.append((lambda x: lambda: x)(r))
...
>>> for f in l:
... f()
...
0
1
2
# etc
Run Code Online (Sandbox Code Playgroud)
unu*_*tbu 24
一种方法是使用具有默认值的参数:
l = []
for r in range(10):
def foo(r = r):
return r
l.append(foo)
for f in l:
print(f())
Run Code Online (Sandbox Code Playgroud)
产量
0
1
2
3
4
5
6
7
8
9
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为它定义了rin foo的局部范围,并在foo定义时将默认值绑定到它.
另一种方法是使用函数工厂:
l = []
for r in range(10):
def make_foo(r):
def foo():
return r
return foo
l.append(make_foo(r))
for f in l:
print(f())
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为它定义r了make_foo本地范围,并在make_foo(r)调用时将值绑定到它.稍后,在f()调用时, r使用LEGB规则查找.虽然r没有在当地范围内foo找到,但是在封闭范围内可以找到make_foo.