Python 对象 之 深浅拷贝原理
赋值
对于任何数据类型,赋值都是创建一个变量,然后对原内存中对象的引用。
>>> num2=num1
>>> str2=str1
>>> dict2= dict1
数字和字符串赋值
字典、列表、元组的赋值
深浅拷贝
import copy #导入copy模块,深浅拷贝的原理内部通过copy模块实现
copy.copy() : 浅拷贝
copy.deepcopy() : 深拷贝
数字和字符串的深浅拷贝
对于 数字 和 字符串 而言,浅拷贝和深拷贝都是复制对象的内存地址,并没有在内存开辟另外一块内存空间创建新的对象,所以并没有意义( 可以把数字和字符串理解成数据类型的最小单元)。
>>> import copy >>> num1=123
>>> num2=copy.copy(num1) >>> num3=copy.deepcopy(num1) >>> print(id(num1),id(num2),id(num3)) 140572605875360 140572605875360 140572605875360 >>> str1='abc'
>>> str2=copy.copy(str1) >>> str3=copy.deepcopy(str1) >>> print(id(str1),id(str2),id(str3)) 140572607345752 140572607345752 140572607345752
字典、元祖、列表的深浅拷贝
浅拷贝:在内存中只额外创建第一层数据
>>> dc1={'k1':123,'k2':'abc','k3':[456,'def']} >>> dc2=copy.copy(dc1)
>>> print(id(dc1['k3']),id(dc2['k3']))# 可以看到两个字典的k3指向不同内存地址
140572345367048 140572345367048
>>> dc2['k3'][1]='xyz' >>> print(dc1,dc2) #可以看到修改了dc2中的列表,dc1中的列表也跟着变了 {'k1': 123, 'k2': 'abc', 'k3': [456, 'xyz']} {'k1': 123, 'k2': 'abc', 'k3': [456, 'xyz']}
深拷贝:在内存中将除了数字和字符串外的所有数据重新创建一份;
>>> dc1={'k1':123,'k2':'abc','k3':[456,'def']} >>> dc2=copy.deepcopy(dc1) >>> print(id(dc1['k3']),id(dc2['k3'])) # 可以看到两个字典的指向不同的内存地址 140572359070024 140572345368648 >>> dc2['k3'][1]='xyz' >>> print(dc1,dc2) #可以看到修改了dc2中的列表,dc1中的列表依然没变
{'k1': 123, 'k2': 'abc', 'k3': [456, 'def']} {'k1': 123, 'k2': 'abc', 'k3': [456, 'xyz']}
深浅拷贝的应用举例
例如有一批机器应用一个监控模板,当cpu> 80%,mem > 80%, disk > 80% 时触发告警,用字典表示如下:
dic = {
'cpu':[80,],
'mem':[80,],
'disk':[80,]
}
有另外一批机器需要应用另外一个监控模板,当cpu> 50%,mem > 80%, disk > 80% 时触发告警,可以对原dic作深拷贝:
newdic=copy.deepcopy(dic)
newdic['cpu'][0]=50
print(dic,newdic) # 可以看到对新模板内列表元素的修改,不会影响到原模板
{'cpu': [80], 'mem': [80], 'disk': [80]} {'cpu': [50], 'mem': [80], 'disk': [80]}