Python中所有型別的值都是物件,這些物件分為可變物件與不可變物件兩種:
-
不可變型別
float、int、str、tuple、bool、frozenset、bytestuple自身不可變,但可能包含可變元素,如:([3, 4, 5], 'tuple')
-
可變型別
list、dict、set、bytearray、自定義型別
+=運算子
+=運算子對應__iadd__魔法方法,對于不可變物件,a+=b和a=a+b等價,對于可變物件并不等價,dict和set不支持+=和+運算子,
l1 = l2 = [1, 2, 3] # 只有l1發生變化 # l1 = l1 + [4] # l1和l2都發生變化,輸出[1, 2, 3, 4, 5] l1 += [4, 5] print(l1) print(l2)
淺拷貝 深拷貝
與賦值不同,拷貝(可能)會產生新的物件,可通過拷貝來避免不同物件間的相互影響,
在Python中,不可變物件,淺拷貝和深拷貝結果一樣,都回傳原物件:
import copy ? ? t1 = (1, 2, 3) t2 = copy.copy(t1) t3 = copy.deepcopy(t1) print(t1 is t2) # True print(t1 is t3) # True print(id(t1), id(t2), id(t3)) # 輸出相同值
對于可變物件,則會產生新物件,只是若原物件中存在可變屬性/欄位,則淺拷貝產生的物件的屬性/欄位參考原物件的屬性/欄位,深拷貝產生的物件和原物件則完全獨立:
l1 = [1, 2, 3] l2 = l1.copy() print(l1 is l2) # False l2[0] = 100 print(l1[0]) # 1
import copy ? ? class Id: def __init__(self, name): self.name = name ? ? class Person: def __init__(self, id: Id): self.id = id ? ? p1 = Person(Id("eason")) p2 = copy.copy(p1) print(p1 is p2) # False print(p1.id is p2.id) # True p2.id.name = "p2" print(p1.id.name) # p2 ? p3 = copy.deepcopy(p1) print(p1 is p3) # False print(p1.id is p3.id) # False print(p1.id.name is p3.id.name) # True,字串不可變,這里name屬性的地址一樣 p3.id.name = "p3" print(p1.id.name) # 還是p2
Python中可使用以下幾種方式進行淺拷貝:
-
使用copy模塊的copy方法
-
可變型別切片
l1 = [1, 2, 3] l2 = l1[:] print(l1 is l2) # False
-
可變型別的copy方法
[].copy() {}.copy() set().copy() -
呼叫list, set, dict方法
l1 = [1, 2, 3] l2 = list(l1) l2[0] = 100 print(l1[0]) # 1
推薦閱讀
Different behaviour for list.__iadd__ and list.__add__
學習Python一年,這次終于弄懂了淺拷貝和深拷貝
copy — Shallow and deep copy operations
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/549811.html
標籤:其他
