Python中的深浅拷贝概念

相关概念

简单来说,一个对象所对应的东西包含但不限于下面两部分:

  • 引用,也就是地址。
  • 数据,也就是值。

还有两个概念是:

  • 可变对象与不可变对象(对象值是否可修改)
  • 容器对象与非容器对象(对象是否可以存放其它对象)

下面举几个重要对象类型的例子。

对象类型可变容器
整数-int
浮点-float
字符串-str
列表-list
字典-dict
元组-tuple

从表中我们就可以看出元组(tuple)比较特殊,那也就意味着意味着在拷贝时也特殊。

深浅拷贝

通俗理解:

  • 深拷贝就是拷贝的东西多,复制了引用,也复制了数据(开辟新内存)。
  • 浅拷贝就是拷贝的东西少,复制了引用,没复制了数据(不开辟新内存)。

实践出真知(踩坑完毕)

引入Python自带的copy库

import copy
# 库中的对应函数,简单例子
a = 1  # 不可变非容器类型变量
b = copy.copy(a)  # 浅拷贝
c = copy.deepcopy(a)  # 深拷贝
# 通过查看内存地址判断深浅
print(id(a))
print(id(b))
print(id(c))

不可变非容器类型代码

import copy
a1 = 1  # 第一层是整数int------是不可变
a2 = 1.1  # 第一层是整数int------是不可变
a3 = 'bryan'  # 第一层是整数int------是不可变
# 浅拷贝
b1 = copy.copy(a1)
b2 = copy.copy(a2)
b3 = copy.copy(a3)
# 深拷贝
c1 = copy.deepcopy(a1)
c2 = copy.deepcopy(a2)
c3 = copy.deepcopy(a3)
# 验证
print(id(a1),id(b1),id(c1))
print(id(a2),id(b2),id(c2))
print(id(a3),id(b3),id(c3))

可变容器类型代码

import copy
# 情况1 顶层是可变类型,下层(第二层及其以下层)都是不可变类型
a = [1, 2]  # 第一层是列表list,第二层是整数int------是不可变类型(第二层)
# # 浅拷贝
b = copy.copy(a)
# # 深拷贝
c = copy.deepcopy(a)
# # 验证
print(id(a), id(b), id(c))
# 情况2 顶层是可变类型,下层存在可变类型
a1 = [1, 2]
a2 = [3, 4]
aa = [a1, a2]  # 第一层是列表list, 第二层是列表list,第三层是整数int------存在可变类型(第二层)
print(id(a1), id(a2))
print(id(aa), id(aa[0]), id(aa[1]))
# # 浅拷贝
bb = copy.copy(aa )
# # 验证
print(id(bb), id(bb[0]), id(bb[1]))
# # 深拷贝
cc = copy.deepcopy(aa)
print(id(cc), id(cc[0]), i
# # 验证d(cc[1]))

不可变容器类型代码

import copy
# 情况1 顶层是不可变类型,下层都是不可变类型
a = (1, 2)  # 第一层是元组tuple,第二层是整数int------是不可变类型(第二层)
# # 浅拷贝
b = copy.copy(a)
# # 深拷贝
c = copy.deepcopy(a)
# # 验证
print(id(a), id(b), id(c))
# 情况2 顶层是不可变类型,下层存在可变类型
a1 = [1, 2]
a2 = [3, 4]
aa = (a1, a2)  # 第一层是元组tuple, 第二层是列表list,第三层是整数int------存在可变类型(第二层)
print(id(a1), id(a2))
print(id(aa), id(aa[0]), id(aa[1]))
# # 浅拷贝
bb = copy.copy(aa)
# # 验证
print(id(bb), id(bb[0]), id(bb[1]))
# # 深拷贝
cc = copy.deepcopy(aa)
# # 验证
print(id(cc), id(cc[0]), id(cc[1]))
# 顶层为可变容器型对象
a = [300, 400]
a1 = 500
b = (600, 700)
b1 = 800
c = (a, a1)  # ([300, 400], 500)
c1 = [b, b1]  # [(600, 700), 800]
d = [c, c1]  # [([300, 400], 500), [(600, 700), 800]]  是一个最深具有四层的对象
e = copy.copy(d)
f = copy.deepcopy(d)
# 验证
print(id(a1), id(b1))
# >>> 140266444072368 140266444071664
print(id(a), id(b), id(a[0]), id(b[0]))
# >>> 140266442385736 140266443371016 140266444073008 140266444074192
print(id(c), id(c1), id(c[0]), id(c1[0]))
# >>> 140266443371272 140266443372936 140266442385736 140266443371016
print(id(d), id(e), id(f))
# >>> 140266442874760 140266442283912 140266443373448
print(id(d[0]), id(e[0]), id(f[0]))  # 对应c
# >>> 140266443371272 140266443371272 140266442362568
print(id(d[1]), id(e[1]), id(f[1]))  # 对应c1
# >>> 140266443372936 140266443372936 140266442295304
print(id(d[0][0]), id(e[0][0]), id(f[0][0]))  # 对应c[0]
# >>> 140266442385736 140266442385736 140266442335880
print(id(d[1][0]), id(e[1][0]), id(f[1][0]))  # 对应c1[0]
# >>> 140266443371016 140266443371016 140266443371016
print(id(d[0][0][0]), id(e[0][0][0]), id(f[0][0][0]))  # 对应a[0]
# >>> 140266444073008 140266444073008 140266444073008
print(id(d[1][0][0]), id(e[1][0][0]), id(f[1][0][0]))  # 对应b[0]
# >>> 140266444074192 140266444074192 140266444074192
# 顶层为不可变容器型对象
a1 = (1, 2)
a2 = [1, 2]
b1 = (3, 4)
b2 = [3, 4]
c1 = (5, 6)
c2 = [5, 6]
d1 = (7, 8)
d2 = [7, 8]

e1 = [a2, b2]
e2 = [a1, b2]
e3 = [a1, b1]

f1 = (c2, d2)
f2 = (c1, d2)
f3 = (c1, d1)

g1 = (e1, e2, e3, f1, f2, f3)
# g1 = [e1, e2, e3, f1, f2, f3]

print(g1)
j1 = copy.copy(g1)
k1 = copy.deepcopy(g1)
print('                                              |    原始    |     原始     |    浅拷贝    |    深拷贝   |')
print('                      第1层空空-不变-混可变:', id(g1), id(g1), id(j1), id(k1))

print('                      第2层不变-可变-全可变:', id(e1), id(g1[0]), id(j1[0]), id(k1[0]))
print('                      第2层不变-可变-混可变:', id(e2), id(g1[1]), id(j1[1]), id(k1[1]))
print('                      第2层不变-可变-全不变:', id(e3), id(g1[2]), id(j1[2]), id(k1[2]))
print('                      第2层不变-不变-全可变:', id(f1), id(g1[3]), id(j1[3]), id(k1[3]))
print('                      第2层不变-不变-混可变:', id(f2), id(g1[4]), id(j1[4]), id(k1[4]))
print('                      第2层不变-不变-全不变:', id(f3), id(g1[5]), id(j1[5]), id(k1[5]))

print('           第3层不变-可变-全可变中可变-全不变:', id(a2), id(g1[0][0]), id(j1[0][0]), id(k1[0][0]))
print('           第3层不变-可变-混可变中不变-全不变:', id(a1), id(g1[1][0]), id(j1[1][0]), id(k1[1][0]))
print('           第3层不变-可变-混可变中可变-全不变:', id(b2), id(g1[1][1]), id(j1[1][1]), id(k1[1][1]))
print('           第3层不变-可变-全不变中不变-全不变:', id(a1), id(g1[2][0]), id(j1[2][0]), id(k1[2][0]))

print('           第3层不变-不变-全可变中可变-全不变:', id(c2), id(g1[3][0]), id(j1[3][0]), id(k1[3][0]))
print('           第3层不变-不变-混可变中不变-全不变:', id(c1), id(g1[4][0]), id(j1[4][0]), id(k1[4][0]))
print('           第3层不变-不变-混可变中可变-全不变:', id(d2), id(g1[4][1]), id(j1[4][1]), id(k1[4][1]))
print('           第3层不变-不变-全不变中不变-全不变:', id(c1), id(g1[5][0]), id(j1[5][0]), id(k1[5][0]))

print('第4层不变-可变-全可变中可变-全不变中全不变-空空:', id(a2[0]), id(g1[0][0][0]), id(j1[0][0][0]), id(k1[0][0][0]))
print('第4层不变-可变-混可变中不变-全不变中全不变-空空:', id(a1[0]), id(g1[1][0][0]), id(j1[1][0][0]), id(k1[1][0][0]))
print('第4层不变-可变-混可变中可变-全不变中全不变-空空:', id(b2[0]), id(g1[1][1][0]), id(j1[1][1][0]), id(k1[1][1][0]))
print('第4层不变-可变-全不变中不变-全不变中全不变-空空:', id(a1[0]), id(g1[2][0][0]), id(j1[2][0][0]), id(k1[2][0][0]))

print('第4层不变-不变-全可变中可变-全不变中全不变-空空:', id(c2[0]), id(g1[3][0][0]), id(j1[3][0][0]), id(k1[3][0][0]))
print('第4层不变-不变-混可变中不变-全不变中全不变-空空:', id(c1[0]), id(g1[4][0][0]), id(j1[4][0][0]), id(k1[4][0][0]))
print('第4层不变-不变-混可变中可变-全不变中全不变-空空:', id(d2[0]), id(g1[4][1][0]), id(j1[4][1][0]), id(k1[4][1][0]))
print('第4层不变-不变-全不变中不变-全不变中全不变-空空:', id(c1[0]), id(g1[5][0][0]), id(j1[5][0][0]), id(k1[5][0][0]))
'''
不可变容器型对象为顶层
([[1, 2], [3, 4]], [(1, 2), [3, 4]], [(1, 2), (3, 4)], ([5, 6], [7, 8]), ((5, 6), [7, 8]), ((5, 6), (7, 8)))
                                          |      原始     |      原始      |     浅拷贝     |     深拷贝    |
                      第1层空空-不变-混可变:  2586646017992   2586646017992   2586646017992   2586646019144
                      第2层不变-可变-全可变:  2586646001544   2586646001544   2586646001544   2586646056584
                      第2层不变-可变-混可变:  2586642499912   2586642499912   2586642499912   2586645922440
                      第2层不变-可变-全不变:  2586646055048   2586646055048   2586646055048   2586646118536
                      第2层不变-不变-全可变:  2586646268040   2586646268040   2586646268040   2586646267592
                      第2层不变-不变-混可变:  2586646267976   2586646267976   2586646267976   2586646267720
                      第2层不变-不变-全不变:  2586646267912   2586646267912   2586646267912   2586646267912
           第3层不变-可变-全可变中可变-全不变:  2586645883336   2586645883336   2586645883336   2586645985480
           第3层不变-可变-混可变中不变-全不变:  2586646121864   2586646121864   2586646121864   2586646121864
           第3层不变-可变-混可变中可变-全不变:  2586646221192   2586646221192   2586646221192   2586646119240
           第3层不变-可变-全不变中不变-全不变:  2586646121864   2586646121864   2586646121864   2586646121864
           第3层不变-不变-全可变中可变-全不变:  2586642963528   2586642963528   2586642963528   2586646270216
           第3层不变-不变-混可变中不变-全不变:  2586646223240   2586646223240   2586646223240   2586646223240
           第3层不变-不变-混可变中可变-全不变:  2586646221832   2586646221832   2586646221832   2586646270472
           第3层不变-不变-全不变中不变-全不变:  2586646223240   2586646223240   2586646223240   2586646223240
第4层不变-可变-全可变中可变-全不变中全不变-空空: 140711794418064 140711794418064 140711794418064 140711794418064
第4层不变-可变-混可变中不变-全不变中全不变-空空: 140711794418064 140711794418064 140711794418064 140711794418064
第4层不变-可变-混可变中可变-全不变中全不变-空空: 140711794418128 140711794418128 140711794418128 140711794418128
第4层不变-可变-全不变中不变-全不变中全不变-空空: 140711794418064 140711794418064 140711794418064 140711794418064
第4层不变-不变-全可变中可变-全不变中全不变-空空: 140711794418192 140711794418192 140711794418192 140711794418192
第4层不变-不变-混可变中不变-全不变中全不变-空空: 140711794418192 140711794418192 140711794418192 140711794418192
第4层不变-不变-混可变中可变-全不变中全不变-空空: 140711794418256 140711794418256 140711794418256 140711794418256
第4层不变-不变-全不变中不变-全不变中全不变-空空: 140711794418192 140711794418192 140711794418192 140711794418192
'''
'''
可变容器型对象为顶层
[[[1, 2], [3, 4]], [(1, 2), [3, 4]], [(1, 2), (3, 4)], ([5, 6], [7, 8]), ((5, 6), [7, 8]), ((5, 6), (7, 8))]
                                           |    原始    |     原始     |    浅拷贝    |    深拷贝   |
                      第1层空空-可变-混可变: 2386590517384 2386590517384 2386603573768 2386603707848
                      第2层可变-可变-全可变: 2386593509064 2386593509064 2386593509064 2386603636744
                      第2层可变-可变-混可变: 2386603648712 2386603648712 2386603648712 2386603770568
                      第2层可变-可变-全不变: 2386603707272 2386603707272 2386603707272 2386603772872
                      第2层可变-不变-全可变: 2386603919048 2386603919048 2386603919048 2386603918664
                      第2层可变-不变-混可变: 2386603918984 2386603918984 2386603918984 2386603918792
                      第2层可变-不变-全不变: 2386603918920 2386603918920 2386603918920 2386603918920
           第3层可变-可变-全可变中可变-全不变: 2386603534664 2386603534664 2386603534664 2386603636872
           第3层可变-可变-混可变中不变-全不变: 2386603773000 2386603773000 2386603773000 2386603773000
           第3层可变-可变-混可变中可变-全不变: 2386603874184 2386603874184 2386603874184 2386585871560
           第3层可变-可变-全不变中不变-全不变: 2386603773000 2386603773000 2386603773000 2386603773000
           第3层可变-不变-全可变中可变-全不变: 2386603773640 2386603773640 2386603773640 2386603921352
           第3层可变-不变-混可变中不变-全不变: 2386603462024 2386603462024 2386603462024 2386603462024
           第3层可变-不变-混可变中可变-全不变: 2386603770248 2386603770248 2386603770248 2386603921224
           第3层可变-不变-全不变中不变-全不变: 2386603462024 2386603462024 2386603462024 2386603462024
第4层可变-可变-全可变中可变-全不变中全不变-空空: 140711794418064 140711794418064 140711794418064 140711794418064
第4层可变-可变-混可变中不变-全不变中全不变-空空: 140711794418064 140711794418064 140711794418064 140711794418064
第4层可变-可变-混可变中可变-全不变中全不变-空空: 140711794418128 140711794418128 140711794418128 140711794418128
第4层可变-可变-全不变中不变-全不变中全不变-空空: 140711794418064 140711794418064 140711794418064 140711794418064
第4层可变-不变-全可变中可变-全不变中全不变-空空: 140711794418192 140711794418192 140711794418192 140711794418192
第4层可变-不变-混可变中不变-全不变中全不变-空空: 140711794418192 140711794418192 140711794418192 140711794418192
第4层可变-不变-混可变中可变-全不变中全不变-空空: 140711794418256 140711794418256 140711794418256 140711794418256
第4层可变-不变-全不变中不变-全不变中全不变-空空: 140711794418192 140711794418192 140711794418192 140711794418192
'''

总结

顶层可为任意对象类型
底层只可是为数字和字符对象类型

不可变非容器型对象为顶层(只有一层所以也为底层):

  • copy.copy():具有相同引用,不开辟新内存。
  • copy.deepcopy():具有相同引用,不开辟新内存。

可变容器型对象为顶层(可嵌套多层):

  • copy.copy():只有顶层具有不同引用,开辟新内存;剩下所有层具有相同引用,不开辟新内存。
  • copy.deepcopy():在嵌套路径中从底层开始连续的具有不可变类型的所有层中的最顶层(以下简称顶不变层)之上的层的对象都具有不同引用,开辟新内存;顶不变层以下的层及其自身的对象具有相同引用,不开辟新内存。

不可变容器型对象为顶层(可嵌套多层):

  • copy.copy():具有相同引用,不开辟新内存。
  • copy.deepcopy():只要嵌套路径中的对象存在可变类型,在具有可变类型的所有层中的最底层(以下简称底变层)之上的层都具有不同引用,开辟新内存;底变层以下的层及其本身具有相同引用,不开辟新内存。

注:此文章仅为作者拙见,如有错误,欢迎读者批评指正 !!!原创文章转载请注明,谢谢。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值