深拷貝和淺拷貝
1、對象的賦值
對象的賦值實際上是對象之間的引用:當創建一個對象,然后將這個對象賦值給另外一個變量的時候,python並沒有拷貝這個對象,而只是拷貝了這個對象的引用。
當對對象做賦值或者是參數傳遞或者作為返回值的時候,總是傳遞原始對象的引用,而不是一個副本。如下所示:
>>> aList = ["kel","abc",123] >>> bList = aList >>> bList.append("add") >>> aList ['kel', 'abc', 123, 'add'] >>> bList ['kel', 'abc', 123, 'add'] >>> id(aList),id(bList) (140041880705648, 140041880705648) |
2、對象的復制
當你想修改一個對象,而且讓原始的對象不受影響的時候,那么就需要使用到對象的復制,對象的復制可以通過三種方法實現:
a、 使用切片操作進行拷貝--slice operation
b、 使用工廠函數進行拷貝,list/dir/set--factoryfunction
c、 copy.copy()--use copymodule
在復制的時候,使用的是淺拷貝,復制了對象,但是對象中的元素,依然使用引用。
如下所示:
>>> person = ["name",["savings",100.00]] >>> hubby = person[:] #切片操作 >>> wifey = list(person) #使用工廠函數 >>> [id(x) for x in person,hubby,wifey] [139797546486384, 139797546556592, 139797546557240] >>> [id(x) for x in hubby] [139797546838128, 139797546485808] >>> [id(x) for x in wifey] [139797546838128, 139797546485808] >>> hubby[0] = "kel" >>> wifey[0] = "jane" >>> hubby[1][1] = 50.0 >>> [id(x) for x in hubby,wifey] [139797546556592, 139797546557240] >>> [id(x) for x in hubby] [139797546592368, 139797546485808] >>> [id(x) for x in wifey] [139797546592416, 139797546485808] >>> hubby ['kel', ['savings', 50.0]] >>> wifey ['jane', ['savings', 50.0]] |
在使用淺拷貝的時候,發現引用的id都是相同的,但是字符串的id卻發生了變化,是因為在python中,字符串是不可變的,從而在每次進行修改的時候,都是新建一個對象,從而引用發生了變化。
在不可變類型中,數字和字符串都是不可變類型,從而在每次修改的時候,都是新創建一個對象。
3、模塊
核心模塊:copy
淺拷貝和深拷貝的操作都可以在copy模塊中找到,其實copy模塊中只有兩個函數可用,copy()進行淺拷貝操作,而deepcopy()進行深拷貝操作
4、拷貝的警告
第一:非容器類型(比如數字,字符串和其他原子類型的對象,例如代碼,類型和xrange對象等)沒有拷貝一說,淺拷貝是完全用切片操作來完成的。
第二:如果元組變量只包含原子類型對象,那么深拷貝將不會進行。
>>> aList = [1,"kel",[1,2,3]] >>> import copy >>> deepList = copy.deepcopy(aList) >>> deepList[2].append("kel") >>> aList [1, 'kel', [1, 2, 3]] >>> deepList [1, 'kel', [1, 2, 3, 'kel']] |