拷贝Python对象、浅拷贝、深拷贝
淺拷貝和深拷貝在C++中出現和使用的較多,python也有相應的用法。
test1 = ['a','c','b','d','f'] print id(test1) test2 = test1 print id(test2)首先是創建了一個列表對象,并將這個對象的引用賦值給test1這個變量,在test2=test1賦值語句中,python沒有拷貝這個對象,只是拷貝了這個對象的引用,所以二者有相同id。
? ?現在創創建一個通用檔案,名為person,然后進行拷貝,一種拷貝方式采用的是切片操作,另一種方式采用工廠方法。
person = ['name',['saving',1000.0]] hubby = person[:] #切片方式進行拷貝 wifey = list(person) #使用工廠函數 print [id(x) for x in person,hubby,wifey]為他們創建了初始有¥100的個人存款賬戶,用戶名改為定制的名字。但是當hubby取走¥50后,他的行為影響到了wifey的賬戶,雖然進行了分開的拷貝操作(希望的是每人都有一個自己獨立的賬號,而不是一個公用的賬號)為什么會出現這樣的情況呢?
hubby[0] = 'jon' wifey[0] = 'jane' print hubby,wifey? ? ? ?原因是僅僅做了一個淺拷貝。對一個對象進行淺拷貝其實是創建了一個類型跟原來對象一樣,其內容是原來對象元素的引用,換句話說,這個拷貝的對象本身是新的,但是他的內容不是。序列類型的淺拷貝是默認類型拷貝,可以以一下幾種方式實施(1)完全切片操作[:];(2)利用工廠函數,比如list(),dict()等;(3)使用copy模塊的copy()函數。
那為什么名字被修改時,另一個人的名字沒有收到影響呢?這是因為在這兩個列表的兩個對象中,第一個對象時不可變對象(字符串類型),而第2個對象時可變的(列表)。正因為如此,當進行淺拷貝時,字符串被顯示的拷貝,并新創建了一個字符串對象,而列表元素只是把它的引用復制了一下。從而改變名字沒有任何問題,但是更改銀行賬戶的任何信息都會引發問題。
print [id(x) for x in hubby] print [id(x) for x in wifey]由于hubby和wifey的銀行賬號是同一個id,這也就是為什么修改一個會影響到另一個的原因。
現在想創建一個個聯合賬戶,這就是一個很不錯的方案。那如果想創建兩個分離的賬戶呢,需要得到一個完全拷貝或者深拷貝--傳建一個新的容器對象,包含原有對象元素(引用)全新拷貝的引用---需要copy.deepcopy()函數
person = ['name',['saving',1000.0]] hubby = person[:] import copy wifey = copy.deepcopy(person) print [id(x) for x in person,hubby,wifey] hubby[0] = 'jon' wifey[0] = 'jane' print hubby,wifeyhubby[1][1] = 2000.0 print hubby,wifey print [id(x) for x in hubby,wifey]關于拷貝的幾點說明:
1、非容器類型(比如數字、字符串和其它“原子”類型的對象,比如代碼、類型和xrange對象等)沒有被拷貝一說,淺拷貝是用完全切片操作來完成的
2、如果元組變量只包含原子類型對象,對它的深拷貝將不會進行。如果把賬戶信息改成元組類型,那即是按照要求使用深拷貝操作也只能得到一個淺拷貝
copy()進行淺拷貝,deepcopy()進行深拷貝
總結
以上是生活随笔為你收集整理的拷贝Python对象、浅拷贝、深拷贝的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 切片索引
- 下一篇: 列表解析和生成器表达式