深拷贝 和 浅拷贝

来源:互联网 发布:信用卡淘宝买东西套现 编辑:程序博客网 时间:2024/06/05 23:48
深拷贝:
拷贝了该对象,而不是仅拷贝其引用
浅拷贝:
仅拷贝对象的引用。
(可以简单的理解成,一个对象由“对象本身 + 指向该对象的指针”两部分组成,深拷贝就是拷贝对象本身,而浅拷贝进拷贝“指向该对象的指针”)


深拷贝 和 浅拷贝 对应 copy 模块的 deepcopy() 和 copy()
其中,深拷贝 只能用 deepcopy(),而浅拷贝也可以使用其他方式。

下面进行详细说明:
1. 浅拷贝可以用切片来实现
>>> person = ['name', ['savings', 100.00]]
>>> person1 = person[:]
>>> [id(x) for x in person]
[140457457343488, 140457456893680]
>>> [id(x) for x in person1]
[140457457343488, 140457456893680]

2. 浅拷贝可以用工厂来实现
>>> person2 = list(person)
>>> [id(x) for x in person2]
[140457457343488, 140457456893680]

为了证明上面的拷贝是浅拷贝,我们来改变其中一个值
>>> person1[1][1] = 50.00
>>> person1, person2
(['joe', ['savings', 50.0]], ['jane', ['savings', 50.0]])
可以看到,修改 person1 的参数,person2 的也改变了。

不过下面的操作可能就有些迷茫了
>>> person1[0] = 'joe'
>>> person1, person2
(['joe', ['savings', 50.0]], ['name', ['savings', 50.0]])
为啥?!
你这不是浅拷贝么?
我修改 person1,为啥 person2 没改过来?!

其实是这样的,person 的第一个对象是字符串类型,而字符串类型是不可变的,因此当进行浅拷贝时,字符串被显示的拷贝,并新创建了一个字符串对象。
而对于第二个参数,因为其是列表,是可变的,所以仅将其引用复制了一遍。

总之,对于不可变的对象,就没有拷贝这一说了,一定是创建了一个新的对象。

那么如何主动进行深拷贝呢?
用 copy.deepcopy() 就可以了
>>> person1 = person[:]
>>> person2 = person[:]
>>> person1, person2
(['name', ['savings', 50.0]], ['name', ['savings', 50.0]])
>>> import copy
>>> person1 = copy.deepcopy(person)
>>> person1[1][1] = 100.00
>>> person1, person2
(['name', ['savings', 100.0]], ['name', ['savings', 50.0]])

最后,关于拷贝操作的几点警告:
1,非容器类型(数字,字符串和其他“原子”类型的对象,像代码、类型和 xrange 对象等)没有拷贝这一说。
2,浅拷贝时用“完全切片”操作来完成的。
3,如果元组变量只包含原子类型对象,则对它的深拷贝将不会进行。
>>> person = ['name', ('savings', 100.00)]
>>> import copy
>>> newperson = copy.deepcopy(person)
>>> [id(x) for x in person, newperson]
[140140153753328, 140140153909976]
>>> [id(x) for x in person]
[140140154203136, 140140153910408]
>>> [id(x) for x in newperson]
[140140154203136, 140140153910408]

0 0
原创粉丝点击