python中的浅拷贝和深拷贝

时间:2022-05-03 22:38:26

这两天又回头看了看python中的赋值、浅拷贝和深拷贝,以前看的时候总觉得他们之间有关系,但又理不清楚,今天总算有了点头绪,所以跟大家分享一下我的理解。

先说说赋值,其实python中的赋值其实是赋值了一个引用,例如:

foo1=1.0

foo2=foo1

用操作符is判断时,你可以发现结果是true,是因为python是先创建了一个对象1.0,然后这个对象的引用又被赋值给了foo1和foo2,但是如果是这样:

foo1=1.0

foo2=1.0

这时你会发现,这其实是创建了两个不同的对象,用内建函数id()可以发现,二者的身份不同;

其实python还有一个特例,例如:

a=1

b=1

你会发现id(a)=id(b),原因是python认为这些小整型是会经常用到的,所以python会缓存一部分小整型。

其次再说说浅拷贝和深拷贝。

序列类型的可以通过三种方式实现浅拷贝,浅拷贝也是默认的拷贝类型:(1)完全切片操作;(2)利用工厂函数,比如list()等;(3)使用copy模块中的copy()函数。然而对于非容器类型没有拷贝这这一说。在《python核心编程》一书中说道,“对一个对象进行浅拷贝其实是新创建了一个类型跟原对象一样,其内容是原来对象元素的引用,换句话说,这个拷贝的对象本身是新的,但是它的内容不是”读完这句话我的理解是浅拷贝其实是赋值,但后来发现不然,因为赋值的结果是他们的身份相同,但是浅拷贝的身份却不同,下面我结合书上的例子以及我自己的想法来说明这句话是什么意思。

fanwei@ubuntu:~$ python
Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56) 
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> person=['name',['saveing',100]]
>>> wife=person[:]
>>> hubb=list(person)
>>> id(person)
3078619916L
>>> id(wife)
3078621548L
>>> id(hubb)
3078621996L

从代码的结果可以看出hubb和wife虽然是person浅拷贝的结果但是他们身份却不同,再看看他们的内容

>>>[id(x) for x in hubby][3078622112L,3078534412L]>>>[id(x) for x in wife][3078622112L,3078534412L]

二者内容的身份却是一样的。从这一点可以看出所谓的“拷贝对象本身是新的“就是之前代码验证的person、hubb和wife的身份不同,”内容是旧的“就是我们刚刚验证的,所以说其实内容的浅拷贝可以看做是”赋值“,你会发现,如果我们将hubb中的’100‘改成’50‘,wife中的’100‘也变成了’50‘这就说明其实内容的浅拷贝就是”赋值“即两个引用指向同一个对象,改变后二者的身份还是相同。此外,由于hubb[0]、wife[0]是字符串,所以他们没有拷贝一说,是创建了一个新的类型,所以当把二者中的’name‘改名后,他们的身份就不同了。对于深拷贝不管是对象和内容身份都是不同的,这点就不再多说了。现在,应该明白所谓的”对象本身是新的,内容是旧的“这句话的真正含义了吧。

参考资料:

http://www.cnblogs.com/wait123/archive/2011/10/10/2206580.html

http://www.01happy.com/python-shallow-copy-and-deep-copy/