首先我們來講講我們python中的可變物件和不可變物件:
可變物件:該物件指向記憶體中的值是可以改變的。實際上是其所指的值直接發生改變,而不是發生複製,或者開闢一個新的地址空間。例如:列表list,字典dict,集合set。
不可變物件:該物件所指向的記憶體中的值是不能被改變的。當改變一個變數時,由於其所指的值不能被改變,相當於把原來的值複製一份到新開闢的地址,再進行改變,並將變數指向這個新的地址空間。例如:數值型別(int、float)、字串str、元組tuple。
python中物件的賦值實際上是物件的引用,例如:
a = [1,2,3]
實際上在電腦內部是生成一個地址將list[1,2,3]
放在這個地址,在賦值給a時,就是講a指向了這個地址。如果此時我們再執行 a = [4,5,6]
,並不是說在我們的記憶體中[1,2,3]
就不存在了,這個列表是一直存在的,只是我們將變數a指向了一個新的列表的地址。
- 下面我們講講淺拷貝(包含可變物件:此處可變為中間的list物件):
>>> alist=[1,2,3,["a","b"]]
>>> b = alist
>>>print b
[1,2,3,[`a`,`b`]]
>>> alist.append(5)
>>>print alist
[1,2,3,[`a`,`b`],5]
>>>print b
[1,2,3,[`a`,`b`],5]
在這個程式塊中,當我們執行alist.append(5)
實際上改變的是alist這個變數指向的list,由於我們的變數b也是指向這個list,所以變數b的值也跟著改變。
- copy.copy()淺拷貝
這個copy.copy沒有拷貝可變物件,即當可變物件發生變化時,所有的變數都會跟著發生變化。
例如:
>>>import copy
>>> c=copy.copy(alist)
>>>print alist;print c
[1,2,3,[`a`,`b`]]
[1,2,3,[`a`,`b`]]
>>> alist.append(5)
>>>print alist;print c
[1,2,3,[`a`,`b`],5]
[1,2,3,[`a`,`b`]]
>>> alist[3]
[`a`,`b`]#這個物件是可變物件
>>> alist[3].append(`cccc`)
>>>print alist;print c
[1,2,3,[`a`,`b`,`cccc`],5]
[1,2,3,[`a`,`b`,`cccc`]]
- copy.deepcopy拷貝了包含可變物件在內的所有物件
>>>import copy
>>> d=copy.deepcopy(alist)#此時d和alist是兩個完全獨立的物件
>>>print alist;print d
[1,2,3,[`a`,`b`]]
[1,2,3,[`a`,`b`]]始終沒有改變
>>> alist.append(5)
>>>print alist;print d
[1,2,3,[`a`,`b`],5]
[1,2,3,[`a`,`b`]]始終沒有改變
>>> alist[3]
[`a`,`b`]
>>> alist[3].append("ccccc")
>>>print alist;print d
[1,2,3,[`a`,`b`,`ccccc`],5]
[1,2,3,[`a`,`b`]]始終沒有改變