Python中的深拷贝与浅拷贝

定义:所谓浅拷贝就是对引用的拷贝;所谓深拷贝就是对对象的资源的拷贝。

1、对于直接赋值(=),有如下三点认识:

  1)、赋值是将一个对象的地址赋值给一个变量,让变量指向该地址(旧瓶装旧酒)。
  2)、修改不可变对象(str、tuple)需要开辟新的空间
  3)、修改可变对象(list等)不需要开辟新的空间

  • 浅拷贝仅仅复制了容器中元素的地址
#对于赋值运算,就是指向同一个内存地址.
s1 = 'alex'
s2 = s1
print(s1, id(s1))    #alex 1996081840344
print(s2, id(s2))    #alex 1996081840344
#当s1的值修改时,内存地址也发生了变化
s1 = 'alex'
print(s1, id(s1))    #alex 1515050615000
s1 = 'alex2'
print(s1, id(s1))    #alex 1515051454624
#当列表l1新增一个值,其内存地址不变
l1 = [1,2,3]
l2 = l1
print(l1, id(l1))   #[1, 2, 3]    1730542337864
print(l2, id(l2))   #[1, 2, 3]    1730542337864
l1.append(4)
print(l1, id(l1))   #[1, 2, 3, 4] 1730542337864
print(l2, id(l2))   #[1, 2, 3, 4] 1730542337864

2、copy浅拷贝,只拷贝父对象,没拷贝子对象,所以原始数据改变,子对象会改变

#切片赋值相当于浅copy,只拷贝值,不拷贝内存地址
l1 = [1,2,3]
l2 = l1[:]
print(l1, id(l1))   #[1, 2, 3] 2685913624392
print(l2, id(l2))   #[1, 2, 3] 2685913645192
l1.append(4)
print(l1, id(l1))   #[1, 2, 3, 4] 2685913624392
print(l2, id(l2))   #[1, 2, 3]    2685913645192
#只拷贝父对象第一次的值,不拷贝内存地址
l1 = [1,2,3]
l2 = l1.copy()
l1.append(666)
print(l1, id(l1))     #[1, 2, 3, 666] 2170284179272
print(l2, id(l2))     #[1, 2, 3]      2170284195976
#对于浅copy来说,第一层都是独立的内存地址,从第二层开始,都是指向同一个内存地址,一变都变
l1 = [1,2,3,[22,33]]
l2 = l1.copy()
l1[3].append(666)
print(l1, id(l1))     #[1, 2, 3, [22, 33, 666]] 1643848253576
print(l2, id(l2))     #[1, 2, 3, [22, 33, 666]] 1643848253704

3、deepcopy深拷贝,包含父对象及其子对象的拷贝,所以原始对象的改变不会造成深拷贝里任何子元素的改变 

#对于深copy来说,无论多少层,在内存中都是两个独立的内存地址
import copy     #引入copy模块

l1 = [1,[22,33]]
l2 = copy.deepcopy(l1)
l1.append(77)
l1[1].append(66)
print(l1, id(l1), id(l1[1]))    #[1, [22, 33, 66], 77] 1756548727112 1756548726920
print(l2, id(l2), id(l2[1]))    #[1, [22, 33]]         1756548728392 1756548728328

总结:  

  1、深浅拷贝都是对源对象的复制,占用不同的内存空间。
  2、不可变类型(数字、字符串、元组)的对象,对于深浅拷贝毫无影响,最终的地址值和值都是相等的。
  3、可变类型(列表、字典):
    =浅拷贝: 值相等,地址相等
    copy浅拷贝:值相等,地址不相等
    deepcopy深拷贝:值相等,地址不相等

原文地址:https://www.cnblogs.com/lioushell/p/8378380.html