Python深浅拷贝&引用详解

Python深浅拷贝&引用详解

一、定义

浅拷贝:只复制最外层的结构,除最外层其余的直接将其地址引用过来。
深拷贝:全部数据/结构都进行复制,(除不可变类型)增大数据独立性,如果深拷贝中,只要发现复制数据中有一个不是不可变类型就重新创建。

python的数据分为可变类型和不可变类型,可变类型有:list,dict,set。不可变类型:number,string,tuple。所以我们分为不可变类型和可变类型两方面来理解深拷贝和浅拷贝。

二、不可变类型拷贝

1.不可变类型

#不可变类型
a = 'abc'
b = 'abc'
print("c的地址:{}".format(id(c)))
print("d的地址:{}".format(id(d)))

#结果
a的地址:57188256
b的地址:57188256

结论:对于不可变类型,a和b指向同一个地址,说明a和b是同一个对象。

2.浅拷贝(可变类型)

a = [1,2,3,4,['a','b']]
b = copy.copy(a)
print("a:{},a的地址:{}".format(a,id(a)))
print("b:{},b的地址:{}".format(b,id(b)))
#结果
a:[1, 2, 3, 4, ['a', 'b']],a的地址:50240408
b:[1, 2, 3, 4, ['a', 'b']],b的地址:50352856

# 对其中不可变元素进行修改
a.append(5)
print("a:{},a的地址:{}".format(a,id(a)))
print("b:{},b的地址:{}".format(b,id(b)))
#结果
a:[1, 2, 3, 4, ['a', 'b'], 5],a的地址:50240408
b:[1, 2, 3, 4, ['a', 'b']],b的地址:50352856

#对其中可变元素进行修改
a[4].append('c')
print("a:{},a的地址:{}".format(a,id(a)))
print("b:{},b的地址:{}".format(b,id(b)))
#结果
a:[1, 2, 3, 4, ['a', 'b', 'c'], 5],a的地址:50240408
b:[1, 2, 3, 4, ['a', 'b', 'c']],b的地址:50352856

结论:对于内层的可变类型数据元素,拷贝的是其地址。当修改其中的不可变类型数据,拷贝后的对象不会跟着改变,如果修改其中的可变类型对象,拷贝后的对象会跟着一起改变。

3.浅拷贝(不可变类型)

a = 'abcdef'
b = copy.copy(a)
print("a:{},a的地址:{}".format(a,id(a)))
print("b:{},b的地址:{}".format(b,id(b)))
#结果
a:abcdef,a的地址:20235456
b:abcdef,b的地址:20235456

#修改
a = 'abc'
print("a:{},a的地址:{}".format(a,id(a)))
print("b:{},b的地址:{}".format(b,id(b)))
#结果
a:abc,a的地址:20160416
b:abcdef,b的地址:20235456

结论:浅拷贝对于不可变类型,类似于直接赋值。

三、可变类型拷贝

1.可变类型

#可变类型
c = [1,2,3]
d = [1,2,3]
print("a的地址:{}".format(id(a)))
print("b的地址:{}".format(id(b)))

#结果
c的地址:59068744
d的地址:58956776

结论:对于可变类型,c和d是两个不同的对象。

2.深拷贝(可变类型)

a = [1,2,3,4,['a','b']]
b = copy.deepcopy(a)
print("a:{},a的地址:{}".format(a,id(a)))
print("b:{},b的地址:{}".format(b,id(b)))
#结果
a:[1, 2, 3, 4, ['a', 'b']],a的地址:58497944
b:[1, 2, 3, 4, ['a', 'b']],b的地址:58610392

# 对其中不可变元素进行修改
a.append(5)
print("a:{},a的地址:{}".format(a,id(a)))
print("b:{},b的地址:{}".format(b,id(b)))
#结果
a:[1, 2, 3, 4, ['a', 'b'], 5],a的地址:58497944
b:[1, 2, 3, 4, ['a', 'b']],b的地址:58610392

#对其中可变元素进行修改
a[4].append('c')
print("a:{},a的地址:{}".format(a,id(a)))
print("b:{},b的地址:{}".format(b,id(b)))
#结果
a:[1, 2, 3, 4, ['a', 'b', 'c'], 5],a的地址:58497944
b:[1, 2, 3, 4, ['a', 'b']],b的地址:58610392

结论: 深拷贝是将原对象里面的所有元素全部拿出来,然后重新用新的内存空间存储,原对象和拷贝后的对象就没有任何关系了,不管原对象如何改变,拷贝后的对象都不会变。

3.深拷贝(不可变类型)

a = 'abcdef'
b = copy.deepcopy(a)
print("a:{},a的地址:{}".format(a,id(a)))
print("b:{},b的地址:{}".format(b,id(b)))
#结果
a:abcdef,a的地址:48809152
b:abcdef,b的地址:48809152

#修改
a = 'abc'
print("a:{},a的地址:{}".format(a,id(a)))
print("b:{},b的地址:{}".format(b,id(b)))
#结果
a:abc,a的地址:48734112
b:abcdef,b的地址:48809152

结论 :对于不可变类型,不管深浅拷贝,拷贝的都是其引用,一旦原对象改变,就相当于是一个新的对象了,拷贝后的对象与原对象没有任何关系了。

四、扩展

引用与赋值:在python中的赋值,实际上都是引用,内在的含义就是用一个标签指向这个内存空间。

x = 10

结论:该语句在执行时,实际上是先在内存空间中创建一个10,然后将x标签指向这个内存空间,因此这才是完整的引用操作。python中所有的赋值操作都是引用,而不是复制这个内存空间创建一个新的空间来存放这个值。

五、引用

[1]https://blog.csdn.net/time_money/article/details/109604550
[2]https://blog.csdn.net/weixin_43959953/article/details/86249452

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花开盛夏^.^

道阻且长,行者将至!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值