Python的深淺copy
27.簡述Python的深淺拷貝以及應用場景?
深淺拷貝的原理
深淺拷貝用法來自copy模塊。
導入模塊:import copy
淺拷貝:copy.copy
深拷貝:copy.deepcopy
字面理解:淺拷貝指僅僅拷貝數據集合的第一層數據,深拷貝指拷貝數據集合的所有層。所以對於只有一層的數據集合來說深淺拷貝的意義是一樣的,比如字符串,數字,還有僅僅一層的字典、列表、元祖等.
對於以下數據深淺拷貝的意義是一樣的(因為數據類型中只有一層):
name = ‘beijing‘ #字符串
age = 12 #數字
list1 = [1,2,3,4] #列表
dic1 = {‘name‘:‘beijing‘,‘age‘:20} #字典
從內存地址來理解深淺拷貝:
深淺拷貝:
字符串,數字的深淺拷貝
>>> import copy
>>> name="hahah" #字符串
>>> name1=copy.copy(name)
>>>
>>> name2=copy.deepcopy(name)
>>> print(id(name),id(name1),id(name2))
11577192 11577192 11577192
>>> sum=111 #數字
>>> sum1=copy.copy(sum)
>>>
>>> sum2=copy.deepcopy(sum)
>>> print(id(sum),id(sum1),id(sum2))
503865568 503865568 503865568
如上圖,對於數字和字符串的深淺拷貝都只是將變量的索引指向了原來的內存地址,例如在sum,sum1,sum2三個變量中,無論修改任意其中一個變量,只是將其指向了另一個內存地址,其他兩個變量不會變,字符串同理。因此,對於 數字 和 字符串 而言,賦值、淺拷貝和深拷貝無意義,因為其永遠指向同一個內存地址。
字典(列表)的深淺拷貝
賦值:
import copy
n1 = {‘k1‘:‘wu‘,‘k2‘:123,‘k3‘:[‘alex‘,678]}
n2 = n1
淺拷貝:
import copy
n1 = {‘k1‘:‘wu‘,‘k2‘:123,‘k3‘:[‘alex‘,678]}
n3 = copy.copy(n1)
深拷貝:
import copy
n1 = {‘k1‘:‘wu‘,‘k2‘:123,‘k3‘:[‘alex‘,678]}
n4 = copy.deepcopy(n1)
深淺拷貝的應用場景
比如在CMDB系統中,我們定義了一個報警模版call給所有的服務器使用,此時有一批特殊應用的服務器需要不通的報警參數,我們既不想單獨新建模版來一個一個添加報警參數,又不想修改默認模版而影響其他機器的報警閾值。此時我們就需要用深拷貝來完成。示例如下:
默認模版:
call = {
‘cpu‘:80,
‘mem‘:80,
‘disk‘:80
}
此時的特殊模版需求是cpu報警閥值要改成75,而不影響默認模版使用
代碼如下:
import copy
#默認模版
call = {
‘cpu‘:[80,],
‘mem‘:[80,],
‘disk‘:[80,]
}
#新模板
new_call = copy.deepcopy(call)
#修改新模版
new_call[‘cpu‘] = 75
#查看新舊模版的值
print(‘新的模版為:%s‘ %(new_call))
print(‘默認模版為:%s‘ %(call))
#打印結果:
#新的模版為:{‘mem‘: 80, ‘disk‘: 80, ‘cpu‘: 75}
#默認模版為:{‘mem‘: 80, ‘disk‘: 80, ‘cpu‘: 80}
#上面的代碼顯示我們只改了新的模版,而默認模版並沒有修改,並且我們用了copy而不是單獨新建模版。
假設我們用淺copy來做結果是這樣的:
import copy
#默認模版
call = {
‘cpu‘:[80,],
‘mem‘:[80,],
‘disk‘:[80,]
}
#新模板
new_call = copy.copy(call)
#修改新模版
new_call[‘cpu‘] = 75
#查看新舊模版的值
print(‘新的模版為:%s‘ %(new_call))
print(‘默認模版為:%s‘ %(call))
#打印的結果:
#新的模版為:{‘mem‘: [80], ‘disk‘: [80], ‘cpu‘: [75]}
#默認模版為:{‘mem‘: [80], ‘disk‘: [80], ‘cpu‘: [75]}
#默認模版和新模版都被修改了,顯然這不是我們要的結果
分析原因:深拷貝的時候python將字典的所有數據在內存中新建了一份,所以如果你修改新的模版的時候老模版不會變。相反,在淺copy 的時候,python僅僅將最外層的內容在內存中新建了一份出來,字典第二層的列表並沒有在內存中新建,所以你修改了新模版,默認模版也被修改了。
本文轉載自:https://www.cnblogs.com/zhuifeng-mayi/p/9179647.html
Python的深淺copy