首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >拉姆达在循环中

拉姆达在循环中
EN

Stack Overflow用户
提问于 2013-11-07 13:42:43
回答 4查看 41.7K关注 0票数 93

考虑到以下代码片段:

代码语言:javascript
复制
# directorys == {'login': <object at ...>, 'home': <object at ...>}
for d in directorys:
    self.command["cd " + d] = (lambda : self.root.change_directory(d))

我希望创建一个包含两个功能的字典,如下所示:

代码语言:javascript
复制
# Expected :
self.command == {
    "cd login": lambda: self.root.change_directory("login"),
    "cd home": lambda: self.root.change_directory("home")
}

但是看起来,生成的两个lambda函数完全相同:

代码语言:javascript
复制
# Result :
self.command == {
    "cd login": lambda: self.root.change_directory("login"),
    "cd home": lambda: self.root.change_directory("login")   # <- Why login ?
}

我真的不明白为什么。你有什么建议吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-11-07 13:52:05

您需要为创建的每个函数绑定d。这样做的一种方法是将其作为具有默认值的参数传递:

代码语言:javascript
复制
lambda d=d: self.root.change_directory(d)

现在,函数中的d使用该参数,尽管它具有相同的名称,并且在创建函数时将计算该参数的默认值。为了帮助你了解这个:

代码语言:javascript
复制
lambda bound_d=d: self.root.change_directory(bound_d)

记住默认值是如何工作的,例如对于列表和dicts这样的可变对象,因为您正在绑定一个对象。

这种带有默认值的参数的习语很常见,但如果您内省函数参数并根据它们的存在来确定该做什么,则可能会失败。您可以使用另一个闭包来避免参数:

代码语言:javascript
复制
(lambda d=d: lambda: self.root.change_directory(d))()
# or
(lambda d: lambda: self.root.change_directory(d))(d)
票数 114
EN

Stack Overflow用户

发布于 2013-11-07 13:47:35

这是由于d被约束的点。lambda函数都指向变量d,而不是它的当前值,因此,当您在下一次迭代中更新d时,所有函数都会看到此更新。

更简单的例子是:

代码语言:javascript
复制
funcs = []
for x in [1,2,3]:
  funcs.append(lambda: x)

for f in funcs:
  print f()

# output:
3
3
3

您可以通过添加一个额外的函数来解决这个问题,如下所示:

代码语言:javascript
复制
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

还可以修复lambda表达式中的作用域。

代码语言:javascript
复制
lambda bound_x=x: bound_x

但是,一般来说,这是,而不是良好实践,因为您已经更改了函数的签名。

票数 31
EN

Stack Overflow用户

发布于 2019-07-31 10:03:08

或者,您可以使用lambda代替functools.partial,在我看来,它具有更清晰的语法。

而不是:

代码语言:javascript
复制
for d in directorys:
    self.command["cd " + d] = (lambda d=d: self.root.change_directory(d))

它将是:

代码语言:javascript
复制
for d in directorys:
    self.command["cd " + d] = partial(self.root.change_directory, d)

或者,下面是另一个简单的例子:

代码语言:javascript
复制
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
票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19837486

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档