Python的類成員變量默認初始值的坑及解決
類成員變量默認初始值的坑
問題發現
一個循環內,缺省值初始化同名變量,其中的list成員不是空,會延續之前同名變量的值。
示例代碼
# Define class class Variant(): # use def __init__(self, price = 500, description = 'default description', values = ['', '', '']): self.price = price self.description = description self.values = values def __str__(self): return 'price: {}, description: {}, values: {}'.format(self.price, self.description, self.values) variant_list = [] # Create instance with same name iteratively for i in range(3): current_variant = Variant() if i == 1: current_variant.values[2] = 'hello' current_variant.price = i current_variant.description = 'description of variant: {}'.format(i) variant_list.append(current_variant) # Test results for variant in variant_list: print(str(variant))
結果
所有實例的values列表值相同
原因
可選參數默認值的設置在Python中隻會被執行一次,也就是定義該函數的時候”如此使用缺省值初始化,list成員指向的是同一個list(地址),如果隻是修改其中一個元素(而不是賦值新的list開辟新內存),那麼所有instance的list成員都會被修改。
解決方法
直接在構造方法中置為空(self.values = ['', '', '']),之後各個修改值
Python默認值參數
簡單粗暴上代碼
def fun(a, b=[]): b += [a] print(b) fun(1) fun(2,[]) fun(3)
是不是看上去很簡單,其實暗藏玄機,請大傢看一下輸出結果,是不是有點讓你疑惑^^~
[1]
[2]
[1, 3]
此時你是否也和我有一樣的疑惑,為什麼 fun(3) 的輸出結果是 [1, 3]?
哈哈,不賣關子瞭,這裡是因為,因為函數被定義好後,隻會生成一次,所以在函數生成的時候定義的變量 b 的默認值也隻會被初始化一次。
因此,當執行fun(1)函數時,沒有給 b 傳參,所以使用的是 b 的默認值,此時 b 的默認值為[1]。
執行fun(2,[])時,給 b 傳瞭一個[]值(恰好和默認值相同,其實是不同的數據),因此便使用的是傳入數據,執行結果便是[2]。
然後在執行fun(3),此刻又沒有給 b 傳參,所以依舊使用的是 b 的默認值, 而 b 的默認值隻會隨著函數的生成被生成一次 ( fun(1) 生成過瞭 ),所以現在的默認值是fun(1)的執行結果[1],因此當fun(3)再次調用時,輸出結果便會是[1, 3]。
如果不行出現當前這種情況,而是在函數每次被調用的時候都初始化一次變量
可以用下面這種寫法
def function(a, b=None): b = b if b else [] # 明確每次重新定義b b += [a] print(b) function(1) function(2, []) function(3)
輸出結果:
[1]
[2]
[3]
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- Python基礎教程之名稱空間以及作用域
- MySQL數據庫中varchar類型的數字比較大小的方法
- Python中關於property使用的小技巧
- Python中的for循環詳情
- python解析.pyd文件的詳細代碼