循环中的 Lambda:了解默认闭包参数
在 Python 编程中,lambda 函数是可用于创建动态代码的匿名函数块。然而,在循环中使用 lambda 时,可能会遇到意外行为。本文探讨了该问题并提供了解决方案。
考虑以下代码片段:
# directorys == {'login': <object at ...>, 'home': <object at ...>} for d in directorys: self.command["cd " + d] = (lambda: self.root.change_directory(d))
目标是创建一个字典 self.command 将命令映射到函数。每个函数都应将目录更改为目录中指定的值。然而,结果却出乎意料:
# Expected: self.command == { "cd login": lambda: self.root.change_directory("login"), "cd home": lambda: self.root.change_directory("home") } # Result: self.command == { "cd login": lambda: self.root.change_directory("login"), "cd home": lambda: self.root.change_directory("login") # <- Why login? }
问题的出现是因为在循环中创建的 lambda 函数共享相同的闭包。当 d 在循环中更新时,它会影响所有 lambda 函数,导致它们引用同一个变量。
解决方案:使用默认闭包参数
解决此问题,引入默认闭包参数。具体方法如下:
lambda d=d: self.root.change_directory(d)
通过将 d 作为具有默认值的参数传递,lambda 中的函数将引用其自己的参数而不是循环变量。这可确保每个函数将目录更改为预期值。
# Another way to bind d: lambda bound_d=d: self.root.change_directory(bound_d)
请记住,可变对象(如列表和字典)的默认值是共享的,因此在绑定这些类型时要小心。
其他闭包技术
如果传递默认参数不理想,请尝试这些替代闭包技术:
嵌套闭包:
(lambda d: lambda: self.root.change_directory(d))(d)
立即调用:
(lambda d=d: lambda: self.root.change_directory(d))()
以上是为什么 Python 循环中的 Lambda 函数会出现意外行为?的详细内容。更多信息请关注PHP中文网其他相关文章!