循環中的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中文網其他相關文章!