預設參數可變性和最小驚訝原則
Python 社群長期以來一直在努力解決「最小驚訝」原則,該原則旨在直覺且符合預期的設計功能。然而,預設參數的可變性令人費解地偏離了這項原則。
考慮以下函數:
def foo(a=[]): a.append(5) return a
Python 新手可能會預期在不帶參數的情況下調用此函數將始終產生一個列表只有一個元素:[5]。然而,實際行為要奇怪得多:
>>> foo() [5] >>> foo() [5, 5] >>> foo() [5, 5, 5] >>> foo() [5, 5, 5, 5]
這種行為引起了一些人的批評,他們認為這是一個「戲劇性的設計缺陷」。然而,它背後有一個邏輯解釋。
Python 中的函數是一流的對象,這意味著它們可以像任何其他類型一樣被操作並分配給變數。執行 def 語句時,會建立一個函數物件。該物件不僅包含函數的程式碼,還包含其預設參數,這些參數儲存為屬性。
預設情況下,預設參數在函數定義時而不是在函數呼叫時計算。這意味著預設參數的狀態可以在程式執行過程中發生變化,從而導致 foo 函數中觀察到的行為。
此設計決策源自於保持一致性的需要。如果在函數呼叫時計算預設參數,則 def 行將成為混合語句,其中部分綁定將在定義和呼叫時發生。這種方法會帶來額外的複雜性和潛在的混亂。
如 effbot 所指出的,這種行為並非沒有實際應用。例如,考慮以下程式碼:
def a(): print("a executed") return [] def b(x=a()): x.append(5) print(x) a executed >>> b() [5] >>> b() [5, 5]
這裡,x 的預設值在函數定義時計算,確保a() 只被呼叫一次,無論b() 被呼叫了多少次
總之,Python 中預設參數的可變性是一種有意的設計選擇,它優先考慮一致性並符合一流函數的原則。雖然它最初看起來可能違反直覺,但它在函數實現方面提供了更好的控制和靈活性。
以上是為什麼 Python 的預設參數可變性似乎違反了最小驚訝原則?的詳細內容。更多資訊請關注PHP中文網其他相關文章!