Python之深浅拷贝简单介绍

1、传递引用与拷贝

在正式学习深浅拷贝之前,我们先要弄清什么是传递引用

除了基本数据类型之外,还存在类的实例对象这个引用数据类型。而一般的"="做赋值操作的时候。对于基本数据类型,实际上是拷贝他的值,但是对于对象而言,其实赋值的只是这个对象的引用,将原对象的引用传递过去,他们实际上还是指向同一个对象。(面向对象的)

#定义一个列表
a=[1,2,3,4]
#把a的值传递给b(把a的值赋给b)
b=a
#来看看b的值
b
>>>1,2,3,4
'''那么问题来了,b的值与a的值一样,是不是说明a的值被拷贝了然后传给b呢?
我们继续往下看:
想要回答这个问题,我们需要知道,
所谓拷贝就是把a的数值复制后在内存中另开辟一个空间进行存储;
那么如果b=a是拷贝a的值的话,那么他们的内存地址应该是不同的,来验证一下: 
'''
id(a)
>>>2156804875464
id(b)
>>>2156804875464
'''
验证的结果表面,b的值并不是a的拷贝,而是a的内存地址引用。
这里有点绕,简单点说:
a的值存储在内存中占一定的内存空间;
而b的值并不是再开辟一个空间进行存储,只是引用了a的内存地址,所以值与a的值一样;
既然b是a地址引用,那么如果改变a的值,按理说b的值也会相应更改,验证一下:
'''
#把列表a的一个元素改为5
a[0]=5
a
>>>[5,2,3,4]
b
>>>[5,2,3,4]

通过上面的解释,大家应该对传递引用与拷贝有了一定的认识,简单来说:传递引用只是引用了内存地址,并不会开辟空间进行存储。因为a和b是一个内存地址,改变a的值,相应的b就会随之更改。

明白了传递引用,我们再来看拷贝:

#拷贝a
import copy
a=[1,2,3,4,5]
a_copy=copy.copy(a)
a_copy
>>>
Out[1]:
[1, 2, 3, 4, 5]
#可以看到a_copy的值与a的值一样,那么内存地址呢?
id(a)
>>>
Out[2]:
2156804090696

id(a_copy)
>>>
Out[3]:
2156803993544

'''
可以看到,值一样,地址不一样;说明a,b两个变量开辟了两个独立的内存空间存储,
所以用copy()方法,是拷贝。
'''

2、浅拷贝与深拷贝

简单的说,所谓的拷贝,就是在内存中开辟一个空间存储相同的值,其特点是值相同,地址不同,也就是两个值都占用内存空间进行独立存储。拷贝为什么又分为浅拷贝和深拷贝,它们有什么区别呢?其实把拷贝分为浅拷贝与深拷贝主要的原因是元素的多层嵌套问题,直接上例子:

  1. 浅拷贝
#定义一个由两层列表组成的值a
a=[1,2,3,[4,5,6]]

#浅拷贝a的值,看看效果
a_copy=copy.copy(a)

#输出浅拷贝的值a_copy
a_copy
Out[4]:
[1, 2, 3, [4, 5, 6]]

#改下a的第一层元素的值,看看浅拷贝的a_copy有没有变化
a[0]=5

#输出更改后a的值
a
Out[5]:
[5, 2, 3, [4, 5, 6]]

#再看下a_copy的值
Out[6]:
[1, 2, 3, [4, 5, 6]]
#*从结果上看,改变a第一层元素的值,其浅拷贝a_copy的值不变
-------------------------------------------------------
#改下a的第二层元素的值,看看浅拷贝的a_copy有没有变化
a[3][1]=9

#输出更改后a的值
a
Out[6]:
[1, 2, 3, [4, 9, 6]]

#再看下a_copy的值
Out[7]:
[1, 2, 3, [4, 9, 6]]
#*从结果上看,改变a第二层元素的值,其浅拷贝a_copy的值改变

2、深拷贝

#定义一个由两层列表组成的值a
a=[1,2,3,[4,5,6]]

#深拷贝a的值,看看效果
a_deepcopy=copy.deepcopy(a)

#输出深拷贝a_deepcopy的值
Out[1]:
[1, 2, 3, [4, 5, 6]]

#改下a的第一层元素的值,看看深拷贝的a_deepcopy有没有变化
a[0]=5

#输出更改后a的值
a
Out[2]:
[5, 2, 3, [4, 5, 6]]

#再看下a_deepcopy的值
Out[3]:
[1, 2, 3, [4, 5, 6]]
#改下a的第一层元素的值,其深拷贝a_deepcopy的值不变
-------------------------------------------------------
#改下a的第二层元素的值,看看拷贝的a_deepcopy有没有变化
a[3][1]=9

#输出更改后a的值
a
Out[4]:
[1, 2, 3, [4, 9, 6]]

#再看下a_deepcopy的值
Out[5]:
[1, 2, 3, [4, 5, 6]]
#*从结果上看,改变a第二层元素的值,其深拷贝a_deepcopy的值依然不变

3、总结

  • 浅拷贝:copy.copy(对象):

只拷贝对象外层(第一层)元素,而对内部元素进行引用;即外层地址改变(独立存储、互不干涉),内层地址不变(地址共享,相互影响)。整体地址改变。简单的说:就是在使用浅拷贝时,改变原值外层元素时,浅拷贝的值不受影响,但是如果是内层元素,浅拷贝的值会相应更改。原因是,浅拷贝只是拷贝了外层的元素,而内层的元素是地址的引用,所以,在浅拷贝的情况下更改内层元素,浅拷贝的值会改变。

  • 深拷贝:deepcopy(对象):

完全拷贝,不论外层内层地址都改变(完全独立,互不影响)。深拷贝产生的副本可以随意修改,而不用担心会影响原始值。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值