1. 程式人生 > 其它 >Python-引用&淺拷貝&深拷貝

Python-引用&淺拷貝&深拷貝

淺拷貝: 指的是重新分配一塊記憶體,建立一個新的物件,但裡面的元素是原物件中各個子物件的引用


深拷貝: 指的是重新分配一塊記憶體,建立一個新的物件,並且將原物件中的元素,以遞迴的方式,通過建立新的子物件拷貝到新物件中

#codding: utf-8

"""
常量值: 在整個程式的完整生命週期中只會建立一次的變數被稱為常量
    1、str、int、 float、bool 這四個型別的值都是常量值,下面的例子中不論怎麼操作都不會建立一個新的值
"""

import copy

a = "cpython"         #建立常量
b = a                 #引用
c = copy.copy(a)      #淺拷貝
d = copy.deepcopy(a)  #深拷貝

"""
執行結果:
id(a)
Out[12]: 140347862604464
id(b)
Out[13]: 140347862604464
id(c)
Out[14]: 140347862604464
id(d)
Out[15]: 140347862604464
"""

a = 10                   #建立常量
b = a                    #引用
c = copy.copy(a)
d = copy.deepcopy(a)
id(a)
Out[20]: 140348122786384
id(b)
Out[21]: 140348122786384
id(c)
Out[22]: 140348122786384
id(d)
Out[23]: 140348122786384

a = 2.4                    #建立常量
b = a                      #引用
c = copy.copy(a)
d = copy.deepcopy(a)
id(a)
Out[28]: 140347862758640
id(b)
Out[29]: 140347862758640
id(c)
Out[30]: 140347862758640
id(d)
Out[31]: 140347862758640

a = True                    #建立常量
b = a                       #引用
c = copy.copy(a)
d = copy.deepcopy(a)

id(a)
Out[36]: 4502985424
id(b)
Out[37]: 4502985424
id(c)
Out[38]: 4502985424
id(d)
Out[39]: 4502985424

#物件值:除了常量值以外,其他一切都是物件(類),例如:class, list, dict, tuple, set, queue, deque....
#物件的特徵是,每次例項化一個物件都會建立new一個新記憶體,因此每次例項化一個物件,它們的id都是獨立的
a = []
b = []

id(a)
Out[42]: 140348133547520
id(b)
Out[43]: 140347588520896

class TEST:
    def __init__(self):
        self.world = "world"
        
a = TEST()
b = TEST()
id(a)
Out[51]: 140348133753232
id(b)
Out[52]: 140347862738592

#引用: python採取完全引用策略,所以像做下面這種操作,並不是複製/拷貝,而是引用

a = []                      #例項化一個列表物件,變數a的指標指向該列表物件
b = a                       #變數b的指標指向a所指向的列表物件
id(a)
Out[55]: 140348133760384
id(b)
Out[56]: 140348133760384

### 拷貝
a = [1,2,3,4]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)
id(a)
Out[61]: 140348135105280
id(b)
Out[62]: 140348135105280
id(c)
Out[63]: 140348135105664     #c分配了一塊新的記憶體
id(d)
Out[64]: 140348133627136     #d分配了一塊新的記憶體 
id(a[0])
Out[65]: 140348122786096      
id(b[0])
Out[66]: 140348122786096      #成員值是常量,拷貝的是引用
id(c[0])
Out[67]: 140348122786096      #成員值是常量,拷貝的是引用
id(d[0])
Out[68]: 140348122786096      #成員值是常量,拷貝的是引用

##淺拷貝
a = [1,2,3,[4,5,6]]
b = a
c = copy.copy(a)
id(a[3])
Out[75]: 140348133697664
id(b[3])
Out[76]: 140348133697664
id(c[3])
Out[77]: 140348133697664

Out[77]: 140348133697664
a[3][0]= 10                            #a[3]發生變化
Out[77]: 140348133697664
b                                      #b[3]引用a[3],所以b[3]也發生變化
Out[79]: [1, 2, 3, [10, 5, 6]]
c
Out[80]: [1, 2, 3, [10, 5, 6]]

b[3][1] = 20                           #b[3]的子物件發生變化
b
Out[82]: [1, 2, 3, [10, 20, 6]]
a                                      #a[3]的子物件也會發生變化
Out[83]: [1, 2, 3, [10, 20, 6]]
c
Out[84]: [1, 2, 3, [10, 20, 6]]

#深拷貝
a = [1,2,3,[4,5,6]]
b = copy.deepcopy(a)
id(a)
Out[87]: 140348133734144              #分配一塊新的記憶體
id(b)
Out[88]: 140348133698496              #分配一塊新的記憶體

a[3][0]=10                           
a
Out[90]: [1, 2, 3, [10, 5, 6]]        #a物件中的子物件發生變化
b                                    
Out[91]: [1, 2, 3, [4, 5, 6]]         #b物件中的子物件仍不變

###結論:
1、不論是淺拷貝還是深拷貝,都不拷貝最終的常量值,而是引用
2、淺拷貝引用的是一維的成員
3、深拷貝遞迴的是建立物件,只有遇到常量值是會引用
三十六般武藝,七十二般變化,修練出個人品牌併發出光芒