Fun*_*ayu 57 python loops anonymous-function
考虑以下代码段:
# directorys == {'login': <object at ...>, 'home': <object at ...>}
for d in directorys:
self.command["cd " + d] = (lambda : self.root.change_directory(d))
Run Code Online (Sandbox Code Playgroud)
我希望创建一个包含两个函数的字典如下:
# Expected :
self.command == {
"cd login": lambda: self.root.change_directory("login"),
"cd home": lambda: self.root.change_directory("home")
}
Run Code Online (Sandbox Code Playgroud)
但看起来生成的两个lambda函数完全相同:
# Result :
self.command == {
"cd login": lambda: self.root.change_directory("login"),
"cd home": lambda: self.root.change_directory("login") # <- Why login ?
}
Run Code Online (Sandbox Code Playgroud)
我真的不明白为什么.你有什么建议吗 ?
Rog*_*ate 74
您需要为每个创建的函数绑定d.一种方法是将其作为带有默认值的参数传递:
lambda d=d: self.root.change_directory(d)
Run Code Online (Sandbox Code Playgroud)
现在函数内部的d使用参数,即使它具有相同的名称,并且在创建函数时评估其默认值.为了帮助您看到这个:
lambda bound_d=d: self.root.change_directory(bound_d)
Run Code Online (Sandbox Code Playgroud)
记住默认值的工作原理,例如列表和dicts等可变对象,因为您绑定了一个对象.
这个具有默认值的参数成语很常见,但如果您内省函数参数并根据它们的存在确定要执行的操作,则可能会失败.您可以使用另一个闭包来避免该参数:
(lambda d=d: lambda: self.root.change_directory(d))()
# or
(lambda d: lambda: self.root.change_directory(d))(d)
Run Code Online (Sandbox Code Playgroud)
rob*_*e_c 20
这是由于d被绑定的点.lambda函数都指向变量 d而不是它的当前值,因此当您d在下一次迭代中更新时,可以在所有函数中看到此更新.
更简单的例子:
funcs = []
for x in [1,2,3]:
funcs.append(lambda: x)
for f in funcs:
print f()
# output:
3
3
3
Run Code Online (Sandbox Code Playgroud)
您可以通过添加其他功能来解决此问题,如下所示:
def makeFunc(x):
return lambda: x
funcs = []
for x in [1,2,3]:
funcs.append(makeFunc(x))
for f in funcs:
print f()
# output:
1
2
3
Run Code Online (Sandbox Code Playgroud)
您还可以修复lambda表达式中的作用域
lambda bound_x=x: bound_x
Run Code Online (Sandbox Code Playgroud)
但是一般来说,这不是一个好习惯,因为你已经改变了你的功能的签名.
或者,lambda您可以使用functools.partial它来代替,在我看来,它具有更清晰的语法。
代替:
for d in directorys:
self.command["cd " + d] = (lambda d=d: self.root.change_directory(d))
Run Code Online (Sandbox Code Playgroud)
这将是:
for d in directorys:
self.command["cd " + d] = partial(self.root.change_directory, d)
Run Code Online (Sandbox Code Playgroud)
或者,这是另一个简单的例子:
numbers = [1, 2, 3]
lambdas = [lambda: print(number)
for number in numbers]
lambdas_with_binding = [lambda number=number: print(number)
for number in numbers]
partials = [partial(print, number)
for number in numbers]
for function in lambdas:
function()
# 3 3 3
for function in lambdas_with_binding:
function()
# 1 2 3
for function in partials:
function()
# 1 2 3
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
18531 次 |
| 最近记录: |