python的深複製和淺複製
阿新 • • 發佈:2019-02-17
# -*- coding:UTF-8 -*- #此次練習主要是討論物件的淺複製和深複製 import copy #淺複製一個object有三種方式:1、slice操作; # 2、copy模組的copy函式; # 3、工廠函式:dict()、list()、tuple() #***********************淺複製********************************* #淺複製沒有完全的複製一個物件,只是建立一個指向原來物件的reference #比如: origList = ['name',['linkin','age']] #原來列表的元素有兩個:string 和 list 型別 #接下來進行三種方式的淺複製: frtList = origList[:] secList = copy.copy(origList) thrList = list(origList) #雖然此時三個list的記憶體地址都是不一樣的,但是list中各個元素與origList的 #各個元素的記憶體地址都是一樣的,只是原來列表元素的reference! #檢視四個列表的元素: for x in (origList,frtList,secList,thrList): print x print ''' stdout: ['name', ['linkin', 'age']] ['name', ['linkin', 'age']] ['name', ['linkin', 'age']] ['name', ['linkin', 'age']] ''' #檢視記憶體地址: for x in (origList,frtList,secList,thrList): print id(x), #不一樣的容器物件地址,其內容本質是一樣的引用 print print '以上是四個list的記憶體地址' #輸出結果: # 28078688 33755424 33537200 33536760(表面:不一樣的容器記憶體地址) #檢視三個list物件元素的記憶體地址: for x in (origList,frtList,secList,thrList): for elements in x: print id(elements), print print '以上是四個list改變前所有元素物件(2個)的記憶體地址' '''輸出結果:(未對各個物件做任何改動,只是單純的進行淺複製) 19580064 35853776 19580064 35853776 19580064 35853776 19580064 35853776 (本質:一樣的元素記憶體地址(表明只是複製 的物件只是建立一個新的容器,裡面的 複製元素只是指向原來origList列表元素的引用)) ''' #針對淺複製的操作,對某一個列表的元素進行操作時,其他的列表對應的元素也會發生改變 #i.e. frtList[1][0] = 'changes' for x in (origList, frtList,secList,thrList): print x print #結果: ''' ['name', ['changes', 'age']] ['name', ['changes', 'age']] ['name', ['changes', 'age']] ['name', ['changes', 'age']] 結果的改變只是因為列表改變的元素是mutable物件 list 如果改變的是immutable物件(string\ int(tuple稍後再討論)),那麼對其他的列表物件沒有任何影響 ''' #例如: frtList[0] = 'changeimmutableElems' for x in (origList, frtList,secList,thrList): print x print ''' 輸出結果: ['name', ['changes', 'age']] ['changeimmutableElems', ['changes', 'age']] ['name', ['changes', 'age']] ['name', ['changes', 'age']] ''' #檢視記憶體地址: print '以下是改變第二list物件frtList後各個列表所有元素的記憶體地址:' for x in (origList, frtList,secList,thrList): for elements in x: print id(elements), print '''結果: 19580064 35853776 35846816 35853776 被改變的元素(immutable物件)記憶體地址改變 19580064 35853776 19580064 35853776 原因:因為string型別是immutable型別,想要對不可改變型別進行改變?那麼只有重新建立 string型別的字串再賦值給frtList[0],那麼此時frtList[0]元素記憶體地址已經改變 然而,如果元素師mutable型別如 list型別,其元素的改變是允許的,改變後的list物件 的記憶體地址還是不變(因為是mutable型別),所以引用發生改變,其他的淺複製元素引用 也發生改變 ''' #************************************深複製**************************** #進行物件的深複製只需要使用deepcopy函式: deepList = copy.deepcopy(origList) print '深複製之後(改變前)的列表物件記憶體地址和內容:' for x in (origList,deepList): print id(x),'-->',x print print '改變前列表元素的記憶體地址和內容:' for x in (origList,deepList): for item in x: print id(item),'-->',item print '''stdout: 深複製之後(改變前)的列表物件記憶體地址和內容: 28602976 --> ['name', ['changes', 'age']] 34150600 --> ['name', ['changes', 'age']] 改變前列表元素的記憶體地址和內容: 23184544 --> name 34149240 --> ['changes', 'age'] 23184544 --> name 34151240 --> ['changes', 'age'] ''' #分別對string、list型別的元素進行改變: print '深複製之後(改變後)的列表物件元素記憶體地址和內容:' deepList[0] = 'strchanges' deepList[1][0] = 'listchanges' for x in (origList,deepList): print id(x),'-->',x print print '改變後列表元素的記憶體地址和內容:' for x in (origList,deepList): for item in x: print id(item),'-->',item print ''' stdout: 深複製之後(改變後)的列表物件元素記憶體地址和內容: 28602976 --> ['name', ['changes', 'age']] #兩個列表互不影響!! 34150600 --> ['strchanges', ['listchanges', 'age']] 改變後列表元素的記憶體地址和內容: 23184544 --> name 34149240 --> ['changes', 'age'] 34175136 --> strchanges 34151240 --> ['listchanges', 'age'] '''