641 字
3 分钟
深拷贝和浅拷贝
可变和不可变
可变类型(mutable):列表,字典;value值改变,id值不变; 不可变类型(immutable):数字,字符串,元组;value值改变,id值也随之改变。
赋值,拷贝和深拷贝
赋值,只是创建一个变量,该变量指向原来内存地址,如下例:
n4 = n3 = n2 = n1 = "123/'Wu'"
浅拷贝,在内存中只额外创建第一层数据,如下图
import copyn1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]}n3 = copy.copy(n1)
深拷贝,在内存中将所有的数据重新创建一份(递归拷贝,排除最后一层,即:python内部对字符串和数字的优化),如下图:
import copyn1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]}n4 = copy.deepcopy(n1)
字符串 数字 元祖拷贝
# 字符串a = 'copytest'b = copy.copy(a)c = copy.deepcopy(a)
if __name__ == '__main__': print(a, id(a)) print(b, id(b)) print(c, id(c))
#============输出结果===============#copytest 49797384copytest 49797384copytest 49797384整型数字,浮点型数字和元祖拷贝结果与字符串拷贝结果相同
列表拷贝
a = [1, 2, 5, [1, 3, 5]]b = copy.copy(a)c = copy.deepcopy(a)b[-1].pop()
if __name__ == '__main__': print(a, id(a)) print(b, id(b)) print(c, id(c))#============输出结果===============#[1, 2, 5, [1, 3]] 50059904[1, 2, 5, [1, 3]] 50007496[1, 2, 5, [1, 3, 5]] 50059584
单例模式下的类的拷贝
def singleton(cls): # 单例装饰器 instances = {}
@wraps(cls) def get_instances(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls]
return get_instances
@singletonclass Animal(): def __init__(self, name): self.name = name
def aloud(self): print(self.name + '123568')
a = Animal('cat')b = copy.copy(a)c = copy.deepcopy(a)c.name = 'dog'd = Animal('adas')
if __name__ == '__main__': print(a, id(a)) a.aloud() print(b, id(b)) b.aloud() print(c, id(c)) c.aloud() print(d, id(d)) d.aloud()
#============输出结果===============#<__main__.Animal object at 0x02F67DD0> 49708496cat123568<__main__.Animal object at 0x02FACD90> 49991056cat123568<__main__.Animal object at 0x02FACAD0> 49990352dog123568<__main__.Animal object at 0x02F67DD0> 49708496cat123568不可变对象类型,没有被拷贝的说法,即便是用深拷贝,查看id的话也是一样的,如果对其重新赋值,也只是新创建一个对象,替换掉旧的而已。 一句话就是,不可变类型,不管是深拷贝还是浅拷贝,地址值和拷贝后的值都是一样的。
总结
1,深浅拷贝都是对源对象的复制,占用不同的内存空间。
2,不可变类型的对象,对于深浅拷贝毫无影响,最终的地址值和值都是相等的。
3,可变类型:
= 赋值(严格说不是拷贝):值相等,地址相等——它只是给同一个对象多起了一个名字,两边会互相影响
copy浅拷贝:值相等,地址不相等
deepcopy深拷贝:值相等,地址不相等






