数据类型(二)、copy模块

首先深拷贝和浅拷贝都是对象的拷贝,都会生成一个看起来相同的对象,他们本质的区别是拷贝出来的对象的地址是否和原对象一样,也就是地址的复制还是值的复制的区别。

什么是可变对象,什么是不可变对象:

可变对象是指,一个对象在不改变其所指向的地址的前提下,可以修改其所指向的地址中的值;

不可变对象是指,一个对象所指向的地址上值是不能修改的,如果你修改了这个对象的值,那么它指向的地址就改变了,相当于你把这个对象指向的值复制出来一份,然后做了修改后存到另一个地址上了,但是可变对象就不会做这样的动作,而是直接在对象所指的地址上把值给改变了,而这个对象依然指向这个地址。

深拷贝和浅拷贝需要注意的地方就是可变对象的拷贝:

在浅拷贝时,拷贝出来的新对象的地址和原对象是不一样的,但是新对象里面的可变元素(如列表)的地址和原对象里的可变元素的地址是相同的,也就是说浅拷贝它拷贝的是浅层次的数据结构(不可变元素),对象里的可变元素作为深层次的数据结构并没有被拷贝到新地址里面去,而是和原对象里的可变元素指向同一个地址,所以在新对象或原对象里对这个可变元素做修改时,两个对象是同时改变的,但是深拷贝不会这样,这个是浅拷贝相对于深拷贝最根本的区别。

copy

copy.copy(x)

返回一个浅拷贝。

deepcopy

copy.deepcopy(x)

返回一个深拷贝。

拷贝详解

  • 拷贝操作直接影响到程序能否正确按照设计思路运行
  • 不正确的拷贝往往不报错,而这也是很多bug的原因

这里直接提供一个直观的例子:

import copy
a = [1,2,3,4,['a','b']]

b = a                   # 赋值
c = a[:]                # 浅拷贝
d = copy.copy(a)        # 浅拷贝
e = copy.deepcopy(a)    # 深拷贝

a.append(5)
a[4].append('c')

print('a=',a)
print('b=',b)
print('c=',c)
print('d=',d)
print('e=',e)

Output:
------------------------------
a= [1, 2, 3, 4, ['a', 'b', 'c'], 5]
b= [1, 2, 3, 4, ['a', 'b', 'c'], 5]
c= [1, 2, 3, 4, ['a', 'b', 'c']]
d= [1, 2, 3, 4, ['a', 'b', 'c']]
e= [1, 2, 3, 4, ['a', 'b']]
------------------------------
  • Python中的直接赋值也只是传递对象
  • 对于copy操作来说,拷贝只进行了一层,之后的引用关系依然保留
  • 最彻底的拷贝操作是deepcopy.其功能与名字一样,会递归深入你的对象,将其里里外外每个层次都拷贝一份
class deepdark():
    def __init__(self):
        self.fantasy=list()
        self.fantasy.append('oh')
    def banana(self):
        print(self.fantasy)
    def boyNextDoor(self):
        self.fantasy.append('my shoulder')

import copy
a = deepdark()
b = [1,a]
c = copy.copy(b)
d = copy.deepcopy(b)

a.boyNextDoor()
a.banana()
b[1].banana()
c[1].banana()
d[1].banana()



Output:
----------------------
['oh', 'my shoulder']
['oh', 'my shoulder']
['oh', 'my shoulder']
['oh']
---------------------
  • 这里可以很容易发现,deepcopy对于类的拷贝是直接生成一个值相同的新对象
>>> e=copy.copy(a)
>>> a.boyNextDoor()
>>> a.banana()
['oh', 'my shoulder', 'my shoulder']
>>> e.banana()
['oh', 'my shoulder', 'my shoulder']

>>> e.boyNextDoor()
>>> e.banana()
['oh', 'my shoulder', 'my shoulder', 'my shoulder']
>>> a.banana()
['oh', 'my shoulder', 'my shoulder', 'my shoulder']

>>> f=copy.deepcopy(a)
>>> a.boyNextDoor()
>>> a.banana()
['oh', 'my shoulder', 'my shoulder', 'my shoulder', 'my shoulder']
>>> f.banana()
['oh', 'my shoulder', 'my shoulder', 'my shoulder']
  • 所以,对于一个类的话,copy只是生成一个引用,而deepcopy才是进行复制
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Wanderer001

ROIAlign原理

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

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

打赏作者

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

抵扣说明:

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

余额充值