Python的類成員變量默認(rèn)初始值的坑及解決
類成員變量默認(rèn)初始值的坑
問題發(fā)現(xiàn)
一個循環(huán)內(nèi),缺省值初始化同名變量,其中的list成員不是空,會延續(xù)之前同名變量的值。
示例代碼
# 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))結(jié)果
所有實(shí)例的values列表值相同
原因
可選參數(shù)默認(rèn)值的設(shè)置在Python中只會被執(zhí)行一次,也就是定義該函數(shù)的時候”如此使用缺省值初始化,list成員指向的是同一個list(地址),如果只是修改其中一個元素(而不是賦值新的list開辟新內(nèi)存),那么所有instance的list成員都會被修改。
解決方法
直接在構(gòu)造方法中置為空(self.values = ['', '', '']),之后各個修改值
Python默認(rèn)值參數(shù)
簡單粗暴上代碼
def fun(a, b=[]): ? ? b += [a] ? ? print(b) fun(1) fun(2,[]) fun(3)
是不是看上去很簡單,其實(shí)暗藏玄機(jī),請大家看一下輸出結(jié)果,是不是有點(diǎn)讓你疑惑^^~
[1]
[2]
[1, 3]
此時你是否也和我有一樣的疑惑,為什么 fun(3) 的輸出結(jié)果是 [1, 3]?
哈哈,不賣關(guān)子了,這里是因?yàn)?,因?yàn)楹瘮?shù)被定義好后,只會生成一次,所以在函數(shù)生成的時候定義的變量 b 的默認(rèn)值也只會被初始化一次。
因此,當(dāng)執(zhí)行fun(1)函數(shù)時,沒有給 b 傳參,所以使用的是 b 的默認(rèn)值,此時 b 的默認(rèn)值為[1]。
執(zhí)行fun(2,[])時,給 b 傳了一個[]值(恰好和默認(rèn)值相同,其實(shí)是不同的數(shù)據(jù)),因此便使用的是傳入數(shù)據(jù),執(zhí)行結(jié)果便是[2]。
然后在執(zhí)行fun(3),此刻又沒有給 b 傳參,所以依舊使用的是 b 的默認(rèn)值, 而 b 的默認(rèn)值只會隨著函數(shù)的生成被生成一次 ( fun(1) 生成過了 ),所以現(xiàn)在的默認(rèn)值是fun(1)的執(zhí)行結(jié)果[1],因此當(dāng)fun(3)再次調(diào)用時,輸出結(jié)果便會是[1, 3]。
如果不行出現(xiàn)當(dāng)前這種情況,而是在函數(shù)每次被調(diào)用的時候都初始化一次變量
可以用下面這種寫法
def function(a, b=None): ? ? b = b if b else [] ?# 明確每次重新定義b ? ? b += [a] ? ? print(b) function(1) function(2, []) function(3)
輸出結(jié)果:
[1]
[2]
[3]
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python實(shí)現(xiàn)的異步代理爬蟲及代理池
本文主要介紹了Python實(shí)現(xiàn)異步代理爬蟲及代理池的相關(guān)知識,具有很好的參考價值,下面跟著小編一起來看下吧2017-03-03
閉包在python中的應(yīng)用之translate和maketrans用法詳解
這篇文章主要介紹了閉包在python中的應(yīng)用之translate和maketrans用法,是比較實(shí)用的技巧,需要的朋友可以參考下2014-08-08
利用Pandas讀取表格行數(shù)據(jù)判斷是否相同的方法
這篇文章主要給大家介紹了關(guān)于利用Pandas讀取表格行數(shù)據(jù)判斷是否相同的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
使用Python實(shí)現(xiàn)在Windows下安裝Django
今天小編就為大家分享一篇關(guān)于使用Python實(shí)現(xiàn)在Windows下安裝Django,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-10-10
Python-jenkins模塊獲取jobs的執(zhí)行狀態(tài)操作
這篇文章主要介紹了Python-jenkins模塊獲取jobs的執(zhí)行狀態(tài)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-05-05
python中常用檢測字符串相關(guān)函數(shù)匯總
這篇文章主要介紹了python中常用檢測字符串相關(guān)函數(shù),實(shí)例匯總了Python針對字符串?dāng)?shù)字、字母、大小寫等常用檢測函數(shù),非常具有實(shí)用價值,需要的朋友可以參考下2015-04-04
python 實(shí)現(xiàn)查詢Neo4j多節(jié)點(diǎn)的多層關(guān)系
今天小編就為大家分享一篇python 實(shí)現(xiàn)查詢Neo4j多節(jié)點(diǎn)的多層關(guān)系,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-12-12

