首页 > 技术文章 > 【个人笔记】Python - 深拷贝与浅拷贝的区别

cxstudy 2019-12-06 15:01 原文

1>浅拷贝

    浅拷贝是copy模块里面的copy方法实现
    浅拷贝后,改变原始对象中为可变类型的元素的值,会同时影响拷贝对象;改变原始对象中为不可变类型的元素的值,不会响拷贝对象。

# 导入copy模块
import copy
list1 = [[1, 2], 3, 4, 5, ]
list2 = copy.copy(list1)
# 查看两个对象的地址,可一看到地址不一样
print(id(list1))
print(id(list2))

    可以看到输出结果,证明两个对象地址是不一样的

 

 

     这时我们尝试改变原始对象list1

# 导入copy模块
import copy
list1 = [[1, 2], 3, 4, 5]
list2 = copy.copy(list1)
# 查看两个对象的地址,可一看到地址不一样
print(id(list1))
print(id(list2))
# 第一个元素地址是否相同?
print(id(list1[0]))
print(id(list2[0]))
# 改变list1的第一个元素的值,查看list2是是否变变化
list1[0][1] = 7
# 神奇的事情发生了,list2也改变了,但是我们没有对list2进行操作呀!
print(list2)
# 向list1增加元素
list1.append(3)
print(list1)
print(list2)

    看一下输出结果:

 

     因此我们可以得到以下结论:

         list2是list1进行浅拷贝(copy)生成的对象,可以看到list1和list2两个对象整体的id是不同的

        但是里面的第1个元素列表的地址却是相同的(指向同一个地址)

        所以list1在相同地址改变元素值时,list2也会改变

        这里在向list1末尾追加元素时,浅拷贝对象没有被追加,是因为在浅拷贝后操作的。

 

2>深拷贝

    深拷贝copy模块里面的deepcopy方法实现

    经过深拷贝后,原始对象和拷贝对象所有的可变元素地址都没有相同的了

 

# 导入copy模块
import copy
list1 = [[1, 2], 3, 4, 5]
list3 = copy.deepcopy(list1)
# 查看两个对象的地址,可一看到地址不一样
print(id(list1))
print(id(list3))
# 第一个元素地址是否相同?
print(id(list1[0]))
print(id(list3[0]))
# 改变list1的第一个元素的值,查看list3是是否变变化
list1[0][1] = 7
# 可以看到list3没有变化
print(list3)
# 向list1增加元素
list1.append(3)
print(list1)
print(list3)

 

      输出结果:

 

 

 

    因此我们可以得到以下结论:

        经过深拷贝(deepcopy)过后,拷贝对象和源对象所有元素地址都不一样,因此无论源对象怎么改变,拷贝对象都不会变

 

 

      总之: 浅拷贝就是藕断丝连,还存在联系 

          深拷贝就是一刀斩断,莫得关系了

 

 

推荐阅读