python為什么對象之間會(huì )共享默認值?

小編:艷芬 922閱讀 2020.08.25

這種類(lèi)型的缺陷通常會(huì )惹惱新手程序員?紤]這個(gè)函數

def foo(mydict={}):? # Danger: shared reference to one dict for all calls
? ? ... compute something ...
? ? mydict[key] = value
? ? return mydict
第一次調用此函數時(shí),mydict 包含一項。第二次,mydict 包含兩項,因為當 foo() 開(kāi)始執行時(shí), mydict 中已經(jīng)有一項了。

函數調用經(jīng)常被期望為默認值創(chuàng )建新的對象。 但實(shí)際情況并非如此。 默認值會(huì )在函數定義時(shí)一次性地創(chuàng )建。 如果對象發(fā)生改變,就如本示例中的字典那樣,則對函數的后續調用將會(huì )引用這個(gè)被改變的對象。

按照定義,不可變對象例如數字、字符串、元組和 None 因為不可變所以是安全的。 對可變對象例如字典、列表和類(lèi)實(shí)例的改變則可能造成迷惑。

由于這一特性,在編程中應遵循的一項好習慣是不使用可變對象作為默認值。 而應使用 None 作為默認值和函數中的值,檢查值為 None 的形參并創(chuàng )建相應的列表、字典或其他可變對象。 例如,不要這樣寫(xiě):

def foo(mydict={}):
? ? ...
而要這樣寫(xiě):

def foo(mydict=None):
? ? if mydict is None:
? ? ? ? mydict = {}? # create a new dict for local namespace
這一特性有時(shí)會(huì )很有用處。 當你有一個(gè)需要進(jìn)行大量耗時(shí)計算的函數時(shí),一個(gè)常見(jiàn)技巧是將每次調用函數的參數和結果值緩存起來(lái),并在同樣的值被再次請求時(shí)返回緩存的值。 這稱(chēng)為“記憶”,具體實(shí)現方式可以是這樣的:

# Callers can only provide two parameters and optionally pass _cache by keyword
def expensive(arg1, arg2, *, _cache={}):
? ? if (arg1, arg2) in _cache:
? ? ? ? return _cache[(arg1, arg2)]

? ? # Calculate the value
? ? result = ... expensive computation ...
? ? _cache[(arg1, arg2)] = result? ? ? ? ? ?# Store result in the cache
? ? return result
你也可以使用包含一個(gè)字典的全局變量而不使用參數默認值;這完全取決于個(gè)人偏好。

關(guān)聯(lián)標簽:
91久久香蕉国产线看观看软件|思思热在线视频精品996|精品无码一区二区三区水蜜桃|久久综合无码中文字幕无码|午夜亚洲AⅤ无码高潮片在线