python默认参数陷阱_python默认参数陷阱
0|1陷阱?
學(xué)過(guò)函數(shù)的人一定聽說(shuō)過(guò)函數(shù)的默認(rèn)參數(shù),關(guān)于函數(shù)的默認(rèn)參數(shù),請(qǐng)看以下的例子:
def extendList(val, lst=[]):
lst.append(val)
return lst
list1 = extendList(10)
list2 = extendList(123, [])
print('list1 = %s' % list1)
print('list2 = %s' % list2)
打印的結(jié)果是?現(xiàn)在,我們將代碼再添加一處,來(lái)看看最后的結(jié)果是什么:
def extendList(val, lst=[]):
lst.append(val)
return lst
list1 = extendList(10)
list2 = extendList(123, [])
list3 = extendList('a')
print('list1=%s' % list1)
print('list2=%s' % list2)
print('list3=%s' % list3)
當(dāng)list1處調(diào)用函數(shù)時(shí),10被加入了列表;list2處調(diào)用函數(shù),123被加入到了新傳入的列表中;最后到list3調(diào)用函數(shù),應(yīng)該將‘a(chǎn)’繼續(xù)加入到列表中返回。因此得到的輸出應(yīng)該是:
# list1 = [10]
# list2 = [233]
# list3 = ['a']
0|1陷阱!
然而,實(shí)際的打印結(jié)果變成了:
陷阱之所以稱之為陷阱,代表我們不能以普通的思維來(lái)看待它,通過(guò)查閱資料,得到以下的一句解釋:
A new list is created?once?when the function is defined, and the same list is used in each successive call.
在定義函數(shù)時(shí),Python的默認(rèn)參數(shù)會(huì)被計(jì)算一次,而不是每次調(diào)用函數(shù)時(shí)(比如Ruby)。這意味著如果你使用一個(gè)可變的默認(rèn)參數(shù)并對(duì)其進(jìn)行改變,那么你將會(huì)直接修改該對(duì)象,該影響將一直延續(xù)到未來(lái)關(guān)于該函數(shù)的調(diào)用(在默認(rèn)參數(shù)沒有被重新賦其他值的情況下)。
眾所周知,Python變量存儲(chǔ)的是變量和值的引用關(guān)系,即實(shí)際變量對(duì)應(yīng)一個(gè)內(nèi)存地址。這意味著Python函數(shù)總是通過(guò)地址傳遞(傳遞參數(shù))工作。調(diào)用函數(shù)時(shí),不會(huì)將參數(shù)值復(fù)制到函數(shù)占位符。相反,我們將占位符指向變量本身。這有一個(gè)非常重要的結(jié)果:我們可以從函數(shù)內(nèi)部更改變量的值。
0|1如何避開陷阱?
None通常是一個(gè)不錯(cuò)的選擇:
def extendList(val, lst = None):
if not lst:
lst = []
lst.append(val)
return lst
有時(shí)您可以專門利用此陷阱來(lái)維護(hù)函數(shù)調(diào)用之間的狀態(tài)。這通常在編寫緩存函數(shù)時(shí)完成。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的python默认参数陷阱_python默认参数陷阱的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 卡车怎么选择 从功能、质量、价格等方面分
- 下一篇: 一汽变速箱怎么样 一汽变速箱品质评测?