在python進行像b = a這樣的賦值時,只會建立乙個對a的新引用,使a的引用計數加1,而不會建立新的物件:
>>> a = 'xyz'>>> import sys
>>> sys.getrefcount(a)
3>>> b = a
>>> sys.getrefcount(b)
4>>> id(a)
88292288l
>>> id(b)
88292288l
這樣,當引用的物件是可變物件的時候(列表,字典,可變集合等),會產生意料之外的行為:
>>> a = [1, 2, 3, 4]>>> b = a
>>> a
[1, 2, 3, 4, 5]
因為a和b引用的是同一物件,改變其中乙個,另外乙個也會隨之改變。當我們想建立乙個副本而不是引用時,可以複製物件。
複製物件一般使用copy模組:
>>> a = [1, 2, 3, 4]>>> import copy
>>> b = copy.copy(a)
>>> b
[1, 2, 3, 4, 5]
>>> a
[1, 2, 3, 4]
這樣就可以了,但這種複製是一種淺複製,複製的新物件中包含的是對原始物件中的項的引用,如果物件的項為可變物件,也會產生不可控行為:
>>> a = [1, [1, 2]]>>> b = copy.copy(a)
>>> b
[1, [1, 2, 3]]
>>> a
[1, [1, 2, 3]]
這時候就要使用深複製了。深複製將建立乙個新物件,並遞迴地複製它所包含的所有物件:
>>> a = [1, [1, 2]]>>> b = copy.deepcopy(a)
>>> b
[1, [1, 2, 3]]
>>> a
[1, [1, 2]]
對於不可改變的物件而言(字串,數字,元組)等,沒有必要拷貝,因為它們是不可改變的,不用擔心會不經意間改動了它們。拷貝操作也只會得到原物件:
>>> a = (1, 2, 3)>>> b = copy.copy(a)
>>> a is b
true
對於可變物件來(列表,字典,可變集合)來說,可以分別使用內建函式list(),dict(),set()來進行淺複製,速度是比使用copy模組快的。
列表也可以使用切片進行淺複製:
>>> a = [1, 2, 3, 4]>>> b = a[:]
>>> a is b
false
>>> b
[1, 2, 3, 4]
對序列資料型別(字串,列表,元組)進行*操作時,也僅僅是複製了物件中項的引用,如果使用*建立乙個多維列表:
>>> a = [1, 2, 3]>>> b = [a]
>>> c = b * 3
>>> c
[[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]
最好是在列表推導中使用淺複製來建立多維列表,可以避免隱式的引用共享:
>>> a = [1, 2, 3]>>> c = [list(a) for i in range(3)]
>>> c
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
Python中物件的引用與複製
在python進行像b a這樣的賦值時,只會建立乙個對a的新引用,使a的引用計數加1,而不會建立新的物件 a xyz import sys sys.getrefcount a 3 b a sys.getrefcount b 4 id a 88292288l id b 88292288l 這樣,當引用...
Python 中的引用與複製
python 中對於乙個物件的操作有引用與複製,但這兩種有乙個很大的區別就是引用物件的修改會影響被引用物件的內容,複製可以分為深複製與淺複製,淺複製的修改共享資料時也會影響被複製物件的內容。在程式中像a b,這樣的賦值時,就會建立乙個對b物件的新引用。對於數字和字串這樣的不可以變的物件,這種賦值實際...
python 引用與複製
a b 這樣的賦值,就會建立對b的引用,對於象數字和字串這樣的不可變的物件,這種賦值實際是建立了b的乙個副本 a hello b a id a id b b is a true a 1000 b hello 對於可變物件,比如字典和列表,a和b引用的是同乙個物件,修改其中任意乙個變數都會影響到另乙個...