Python的類成員變量默認(rèn)初始值的坑及解決
類成員變量默認(rèn)初始值的坑
問題發(fā)現(xiàn)
一個(gè)循環(huán)內(nèi),缺省值初始化同名變量,其中的list成員不是空,會(huì)延續(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中只會(huì)被執(zhí)行一次,也就是定義該函數(shù)的時(shí)候”如此使用缺省值初始化,list成員指向的是同一個(gè)list(地址),如果只是修改其中一個(gè)元素(而不是賦值新的list開辟新內(nèi)存),那么所有instance的list成員都會(huì)被修改。
解決方法
直接在構(gòu)造方法中置為空(self.values = ['', '', '']),之后各個(gè)修改值
Python默認(rèn)值參數(shù)
簡(jiǎn)單粗暴上代碼
def fun(a, b=[]): ? ? b += [a] ? ? print(b) fun(1) fun(2,[]) fun(3)
是不是看上去很簡(jiǎn)單,其實(shí)暗藏玄機(jī),請(qǐng)大家看一下輸出結(jié)果,是不是有點(diǎn)讓你疑惑^^~
[1]
[2]
[1, 3]
此時(shí)你是否也和我有一樣的疑惑,為什么 fun(3) 的輸出結(jié)果是 [1, 3]?
哈哈,不賣關(guān)子了,這里是因?yàn)?,因?yàn)楹瘮?shù)被定義好后,只會(huì)生成一次,所以在函數(shù)生成的時(shí)候定義的變量 b 的默認(rèn)值也只會(huì)被初始化一次。
因此,當(dāng)執(zhí)行fun(1)函數(shù)時(shí),沒有給 b 傳參,所以使用的是 b 的默認(rèn)值,此時(shí) b 的默認(rèn)值為[1]。
執(zhí)行fun(2,[])時(shí),給 b 傳了一個(gè)[]值(恰好和默認(rèn)值相同,其實(shí)是不同的數(shù)據(jù)),因此便使用的是傳入數(shù)據(jù),執(zhí)行結(jié)果便是[2]。
然后在執(zhí)行fun(3),此刻又沒有給 b 傳參,所以依舊使用的是 b 的默認(rèn)值, 而 b 的默認(rèn)值只會(huì)隨著函數(shù)的生成被生成一次 ( fun(1) 生成過了 ),所以現(xiàn)在的默認(rèn)值是fun(1)的執(zhí)行結(jié)果[1],因此當(dāng)fun(3)再次調(diào)用時(shí),輸出結(jié)果便會(huì)是[1, 3]。
如果不行出現(xiàn)當(dāng)前這種情況,而是在函數(shù)每次被調(diào)用的時(shí)候都初始化一次變量
可以用下面這種寫法
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]
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python實(shí)現(xiàn)的爬取小說爬蟲功能示例
這篇文章主要介紹了Python實(shí)現(xiàn)的爬取小說爬蟲功能,結(jié)合實(shí)例形式分析了Python爬取頂點(diǎn)小說站上的小說爬蟲功能相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-03-03mac系統(tǒng)下安裝pycharm、永久激活、中文漢化詳細(xì)教程
這篇文章主要介紹了mac系統(tǒng)下安裝pycharm、永久激活、中文漢化詳細(xì)教程,需要的朋友可以參考下2020-11-11使用PyCharm配合部署Python的Django框架的配置紀(jì)實(shí)
這篇文章主要介紹了使用PyCharm配合部署Python的Django框架的配置紀(jì)實(shí),PyCharm是一款強(qiáng)大的Python的IDE,需要的朋友可以參考下2015-11-11Windows下的Python 3.6.1的下載與安裝圖文詳解(適合32位和64位)
這篇文章主要介紹了Windows下的Python 3.6.1的下載與安裝圖文詳解(適合32位和64位),需要的朋友可以參考下2018-02-02利用Python開發(fā)實(shí)現(xiàn)簡(jiǎn)單的記事本
最近想對(duì)python加深學(xué)習(xí)一下,同時(shí)也是想試著做一些東西,所以使用python,結(jié)合Tkinter來做一個(gè)簡(jiǎn)單的跨平臺(tái)記事本。最終實(shí)現(xiàn)的記事本如下,也算是麻雀雖小,五臟俱全了,之后也是會(huì)繼續(xù)完善的。文中通過圖文及示例代碼介紹的很詳細(xì),有需要的朋友們可以參考借鑒。2016-11-11python使用win32com在百度空間插入html元素示例
這篇文章主要介紹了python使用win32com在百度空間插入html元素的示例,大家參考使用吧2014-02-02圖文詳解感知機(jī)算法原理及Python實(shí)現(xiàn)
感知機(jī)是二類分類的線性分類模型,其輸入為實(shí)例的特征向量,輸出為實(shí)例的類別(取+1和-1二值)。本文將為大家詳細(xì)講講感知機(jī)算法的原理及實(shí)現(xiàn),需要的可以參考一下2022-08-08python利用opencv調(diào)用攝像頭實(shí)現(xiàn)目標(biāo)檢測(cè)
這篇文章主要為大家介紹了python利用opencv調(diào)用攝像頭實(shí)現(xiàn)目標(biāo)檢測(cè)的示例代碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05