Pytoh随笔之浅拷贝与深拷贝的区别

 在Python中,对变量进行赋值操作,实际是一个浅拷贝动作,将赋值号右边的对象引用赋给了赋值号左边的变量。

s = "abcdefg"

如上面这句代码,实际是先创建一个字符串对象,内容为abcdefg,然后将该对象的引用赋给变量s。同样的,如果将s再赋值给另一个字符串变量s1,同样也是将引用赋给s1,所以对s1的修改,会影响s的内容,因为他们是指向同一样内存地址。

对于简单数据类型,浅拷贝和深拷贝是没有区别的。但是对于复杂的数据类型,如列表,字典,类,或是其它自定义的可嵌套的数据类型,浅拷贝和深拷贝还是有区别的,下面以字典类型为例进行说明。

 

import copy

d1 = {"Name":"Chris", "Account":{"RMB": 1000, "USD": 12345}}
d2 = copy.copy(d1)
d3 = dict(d1)
d4 = d1

print [id(x) for x in d1, d2, d3, d4]

d2["Name"] = "Martin" #修改d2中的Name值
d2["Account"]["RMB"] = 2000 #修改d2中的人民币帐户金额
print [x for x in d1, d2, d4] #输出d1, d2, d4内容,d4和d1内容相同,修改d2的人民币帐户金额会影响到d1中的人民币帐户金额
d3["Name"] = "Vivian" #修改d3中的Name值
d3["Account"]["RMB"] = 3000 #修改d3中的人民币帐户金额
print [x for x in d1, d3, d4] #输出d1, d3, d4内容,d4和d1内容相同,修改d3的人民币帐户金额会影响到d1中的人民币帐户金额

d3 = copy.deepcopy(d1)
d3["Name"] = "Vivian" #修改d3中的Name值
d3["Account"]["RMB"] = 6000 #修改d3中的人民币帐户金额
print [x for x in d1, d3, d4] #输出d1, d3, d4内容,d4和d1内容相同,修改d3的人民币帐户金额不会影响到d1中的人民币帐户金额


输出的结果为

[13744000, 13745872, 13746016, 13744000]
[{'Account': {'RMB': 2000, 'USD': 12345}, 'Name': 'Chris'}, {'Account': {'RMB': 2000, 'USD': 12345}, 'Name': 'Martin'}, {'Account': {'RMB': 2000, 'USD': 12345}, 'Name': 'Chris'}]
[{'Account': {'RMB': 3000, 'USD': 12345}, 'Name': 'Chris'}, {'Account': {'RMB': 3000, 'USD': 12345}, 'Name': 'Vivian'}, {'Account': {'RMB': 3000, 'USD': 12345}, 'Name': 'Chris'}]
[{'Account': {'RMB': 3000, 'USD': 12345}, 'Name': 'Chris'}, {'Account': {'RMB': 6000, 'USD': 12345}, 'Name': 'Vivian'}, {'Account': {'RMB': 3000, 'USD': 12345}, 'Name': 'Chris'}]


首先,我们在第3行定义了一个字典变量d1,第4到6行分别用COPY模块中的COPY方法(浅拷贝),工厂方法(dict)和赋值号将赋值给d2,d3和d4。

第8行语句输出这四个变量的内存地址,可以发现,d1和d4指向同一个地址,这证实了我们前面说的,赋值号是对引用进行赋值。

d2和d3有着自己的内存地址且与d1不同,这说明COPY函数和工厂方法(dict)会新开辟内存空间,并将赋值号右边的内容复制到新的内存地址。

第10到15行代码修改变量d2和d3的内容及其子对象(Account是他们的子对象)中的内容,可以发现d2和d3中的Key为Name的值发生了变化,没有影响d1中的值;可是我们修改d2和d3中Key为Account中的RMB的值时,变量d1的RMB值也跟着发生了变化,这说明了执行浅拷贝操作,只是会复制父对象内容,其子对象仍然是引用,也就是说d1,d2和d3中的Account对象是同指向同一个内存地址,所以无论我们是对d2还是d3中的Account进行修改时都会影响到d1中的Account值。如果想让这三个变量中是子对象互不影响,我们就需要用到COPY模块中的deepcopy方法。

第17到20行代码就是使用了deepcopy方法,对d3的子对象修改不会影响到d1的子对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值