您好,登錄后才能下訂單哦!
這篇文章主要介紹“python函數(shù)的默認(rèn)參數(shù)為什么不可以定義可變類型”,在日常操作中,相信很多人在python函數(shù)的默認(rèn)參數(shù)為什么不可以定義可變類型問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”python函數(shù)的默認(rèn)參數(shù)為什么不可以定義可變類型”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!
經(jīng)常會(huì)看到這樣一句代碼警告:
Default argument value is mutable
意思是告訴我們函數(shù)的定義中,使用可變類型做默認(rèn)參數(shù)。
那為什么會(huì)有這個(gè)警告呢?
可變類型(mutable):列表,字典
不可變類型(unmutable):數(shù)字,字符串,元組
def fun(a=[]): a.append(1) print(a) if __name__ == "__main__": fun() fun() >>> [1] [1, 1]
可以發(fā)現(xiàn),默認(rèn)參數(shù)定義可變類型之后,在第二次乃至更多次地調(diào)用同一個(gè)函數(shù)時(shí),默認(rèn)參數(shù)仿佛失去了效果。
此時(shí),在需要重復(fù)調(diào)用同一個(gè)函數(shù)的場(chǎng)景中,就非常容易導(dǎo)致問題,并且該問題不易察覺。在debug的時(shí)候就會(huì)表現(xiàn)成明明沒有參數(shù)傳進(jìn)來,但是函數(shù)參數(shù)會(huì)有值,并且執(zhí)行了不應(yīng)該執(zhí)行的操作。
我的理解:
我們定義的函數(shù)本身是一個(gè)function的實(shí)例化對(duì)象,每當(dāng)我們進(jìn)行函數(shù)的定義時(shí),就是創(chuàng)建了一個(gè)function的實(shí)例化對(duì)象,而默認(rèn)參數(shù)就是其屬性。
在沒有傳入?yún)?shù),以默認(rèn)參數(shù)形式調(diào)用,并且改變了函數(shù)對(duì)象的屬性值時(shí),改變的屬性值被保存下來,當(dāng)?shù)诙握{(diào)用同一個(gè)對(duì)象時(shí),屬性值已經(jīng)發(fā)生了改變。
type(fun) >>> function
def fun(a=None): if a is None: a = [] a.append(1) print(a) if __name__ == "__main__": fun() fun() >>> [1] [1]
請(qǐng)先看代碼,看看代碼的輸出是否和你想的一樣。
def e(v,l=[]): l.append(v) return l l1=e(10) l2=e(123,[]) l3=e("a") print(l1,l2,l3) # 輸出: ([10, 'a'], [123], [10, 'a'])
關(guān)于上述代碼,標(biāo)準(zhǔn)解釋是:帶有默認(rèn)參數(shù)的表達(dá)式在函數(shù)被定義的時(shí)候被計(jì)算,不是在調(diào)用的時(shí)候計(jì)算。
我覺得通俗的解釋是:當(dāng)不傳默認(rèn)值的時(shí)候,無論調(diào)用多少次該函數(shù),在函數(shù)體內(nèi)部使用的一直都是那個(gè)默認(rèn)的“l(fā)”,而這個(gè)默認(rèn)的“l(fā)”又是可變類型,所以,它的改變會(huì)影響所有指向它的變量,也就是l1和l3。
為了使以上兩點(diǎn)的觀點(diǎn)更加站的住腳,我進(jìn)行以下幾個(gè)測(cè)試。
def e(k,v,d={}): d[k]=v return d d1=e(10,10) d2=e(123,123,{}) d3=e("a","a") print(d1,d2,d3) # 輸出:({'a': 'a', 10: 10}, {123: 123}, {'a': 'a', 10: 10})
def e(v,s=""): s = s+v return s s1=e("我") s2=e("a","") s3=e("是") print(s1,s2,s3) # 輸出: 我 a 是
其實(shí)以上類型都已經(jīng)說明問題了,但是寫個(gè)文章不容易,我決定用元祖包列表,看看修改這個(gè)列表中的數(shù)據(jù)會(huì)怎樣。
實(shí)際上是不用測(cè)試的,最終打印出來的數(shù)據(jù)一定是類似**“可變類型時(shí)的操作”**時(shí)的輸出的。
為什么?因?yàn)槲覜]有修改元祖本身,修改的是其可變類型列表啊。
不能扯遠(yuǎn)了,不然扯到深拷貝,淺拷貝了。
def e(v,t=([],)): # 傳遞有元素的元祖的時(shí)候要記得帶逗號(hào)哦。 t[0].append(v) # t = t[0].append(v) 要知道t[0].append(v)是沒有返回值的,t會(huì)指向None,如果這樣返回,外部打印的全部為None,所以不可以這樣返回。 # 而且 如果你想 t[0]= t[0].append(v) 也是不行的,為啥?你在ipython中輸入 dir(())你就知道了。 # 好吧,其實(shí)是因?yàn)樵媸强勺x不可寫的。它能切片、遍歷就已經(jīng)很不錯(cuò)了。。。。。 return t t1=e("我") t2=e("a",([],)) t3=e("是") print(t1,"\n",t2,"\n",t3) # 輸出: # (['我', '是'],) # (['a'],) # (['我', '是'],)
到此,關(guān)于“python函數(shù)的默認(rèn)參數(shù)為什么不可以定義可變類型”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。