在Python中復(fù)制list或其他可變集合時,使用的類型構(gòu)造方法或切片默認(rèn)的都是淺復(fù)制遏弱,也就是說對于對象中的對象只是復(fù)制了一個地址剑按,如下。
如果在容器中有可變對象的引用可能會造成無法預(yù)期的結(jié)果肺然。
+=運(yùn)算符對于list來說會原地修改list的內(nèi)容, 對于tuple來說則會重新創(chuàng)建一個對象并賦值給原引用變量腿准。
為任意對象做淺復(fù)制和深復(fù)制
有些時候我們可能也需要深復(fù)制(即副本不共享內(nèi)部對象的引用)际起,我們可以使用copy模塊提供的copy、deepcopy函數(shù)吐葱,他能為任意對象做淺復(fù)制和深復(fù)制街望。
函數(shù)參數(shù)作為引用時:
這種情況下函數(shù)形參為實參(引用類型)的副本,函數(shù)可能會修改作為參數(shù)傳入的引用指向的對象弟跑,但不能將這個對象替換灾前。
使用可變類型作為參數(shù)默認(rèn)值引起的問題:
沒有初始化的默認(rèn)參數(shù)會指向同一個對象。
出現(xiàn)這個問題的根源是參數(shù)默認(rèn)值會在函數(shù)對象定義時計算(通常在加載模塊時)孟辑,因此參數(shù)默認(rèn)值成為了函數(shù)對象的屬性哎甲,當(dāng)這個默認(rèn)值為可變類型時就容易出現(xiàn)我們意料之外的事情。
我們觀察上述例子中t函數(shù)對象的__default__屬性:
我們每次調(diào)用t這個函數(shù)對象時饲嗽,其實是共享了這個函數(shù)對象的默認(rèn)值炭玫,對于值為可變類型的參數(shù)來說每次調(diào)用實際上操作的是同一個對象,對于上述例子來說每次調(diào)用時l默認(rèn)都只是t函數(shù)對象__defaults__屬性(包含有個或多個默認(rèn)值)中某一個元素的別名而已喝噪。
具體請看下面的例子:
這也是我們?yōu)槭裁磿⒑瘮?shù)參數(shù)的默認(rèn)值設(shè)置為None础嫡。