Python深拷贝和浅拷贝

1. Python引用计数[ http://blog.chinaunix.net/uid-26602509-id-3506965.html ]

  1.1 引用计数机制

    引用计数是计算机编程语言中的一种内存管理技术,是指将资源(可以是对象、内存或磁盘空间等等)的被引用次数保存起来,当被引用次数变为零时就将其释放的过程。使用引用计数技术可以实现自动资源管理的目的。同时引用计数还可以指使用引用计数技术回收未使用资源的垃圾回收算法。

    当创建一个对象的实例并在堆上申请内存时,对象的引用计数就为1,在其他对象中需要持有这个对象时,就需要把该对象的引用计数加1,需要释放一个对象时,就将该对象的引用计数减1,直至对象的引用计数为0,对象的内存会被立刻释放。

  1.2 垃圾回收

    当对象的引用计数为0,对象的内存会被立刻释放,称为垃圾回收

  1.3 引用计数增加情况

    (1). 对象被创建:x=4

    (2). 另外的别人被创建:y=x

    (3). 被作为参数传递给函数:foo(x)

    (4). 作为容器对象的一个元素:a=[1,x,‘33‘]

  1.4 引用计数减少情况

    (1). 一个本地引用离开了它的作用域。比如上面的foo(x)函数结束时,x指向的对象引用减1。

    (2). 对象的别名被显式的销毁:del x ;或者del y

    (3). 对象的一个别名被赋值给其他对象:x=789

    (4). 对象从一个窗口对象中移除:myList.remove(x)

    (5). 窗口对象本身被销毁:del myList,或者窗口对象本身离开了作用域。

 


 

2. 深浅拷贝[ http://www.cnblogs.com/wait123/archive/2011/10/10/2206580.html ]

  2.1 赋值    

    其实python中的赋值其实是使引用计数+1,例如:

foo1 = 1.0
foo2 = foo1
foo1 is foo2   #True
id(foo1) = 18719720
id(foo2) = 18719720

    

    但是如果是这样:

foo1=1.0
foo2=1.0
foo1 is foo2    #False
id(foo1) = 18719888
id(foo2) = 18719840

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

 

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

a = 1
b = 1
id(a) = 14332248
id(b) = 14332248

    原因是python认为这些小整型是会经常用到的,所以python会缓存一部分小整型。

    

  2.2 深拷贝 & 浅拷贝

    序列类型的可以通过三种方式实现浅拷贝,浅拷贝也是默认的拷贝类型:(1)完全切片操作;(2)利用工厂函数,比如list()等;(3)使用copy模块中的copy()函数。

    在《Python核心编程》一书中说道,“对一个对象进行浅拷贝其实是新创建了一个类型跟原对象一样,其内容是原来对象元素的引用,换句话说,这个拷贝的对象本身是新的,但是它的内容不是”。

import copy
a = [1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘]]
b = a
c = copy.copy(a)

id(a)       #139879301469392
id(b)       #139879301469392        
id(c)       #139879298646816, 可以看出所谓的“拷贝对象本身是新的“

[id(x) for x in a]        #[14332248, 14332224, 14332200, 14332176, 139879298781912]
[id(x) for x in b]        #[14332248, 14332224, 14332200, 14332176, 139879298781912]
[id(x) for x in c]        #[14332248, 14332224, 14332200, 14332176, 139879298781912], 即”内容是旧的“

 

  最后,深拷贝和浅拷贝的区别^_^

import copy
a = [1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘]]
c = copy.copy(a)
d = copy.deepcopy(a)

id(a)       #139879301469392  
id(c)       #139879298646816
id(d)       #139879301462784

[id(x) for x in a]        #[14332248, 14332224, 14332200, 14332176, 139879298781912]
[id(x) for x in c]        #[14332248, 14332224, 14332200, 14332176, 139879298781912]
[id(x) for x in d]        #[14332248, 14332224, 14332200, 14332176, 139879302072512]

##################################
a.append(5)
a[4].append(‘hello‘)

a        #[1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘, ‘hello‘], 5]
c        #[1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘, ‘hello‘]]
d        #[1, 2, 3, 4, [‘a‘, ‘b‘, ‘c‘]]

[id(x) for x in a]        #[14332248, 14332224, 14332200, 14332176, 139879298781912, 14332152]
[id(x) for x in c]        #[14332248, 14332224, 14332200, 14332176, 139879298781912]
[id(x) for x in d]        #[14332248, 14332224, 14332200, 14332176, 139879302072512]

#################################
a[1] = 0
c[2] = 0
d[3] = 0

a        #[1, 0, 3, 4, [‘a‘, ‘b‘, ‘c‘, ‘hello‘], 5]
c        #[1, 2, 0, 4, [‘a‘, ‘b‘, ‘c‘, ‘hello‘]]
d        #[1, 2, 3, 0, [‘a‘, ‘b‘, ‘c‘]]

[id(x) for x in a]        #[14332248, 14332272, 14332200, 14332176, 139879298781912, 14332152]  a[1]关联到新对象
[id(x) for x in c] #[14332248, 14332224, 14332272, 14332176, 139879298781912]  c[2]关联到新对象
[id(x) for x in d] #[14332248, 14332224, 14332200, 14332272, 139879302072512]  d[3]关联到新对象
################################
# 1
del a[0]
a        #[ 0, 3, 4, [‘a‘, ‘b‘, ‘c‘, ‘hello‘], 5]
c        #[1, 2, 0, 4, [‘a‘, ‘b‘, ‘c‘, ‘hello‘]]
d        #[1, 2, 3, 0, [‘a‘, ‘b‘, ‘c‘]]

del c[0]
a        #[   0, 3, 4, [‘a‘, ‘b‘, ‘c‘, ‘hello‘], 5]
c        #[ 2, 0, 4, [‘a‘, ‘b‘, ‘c‘, ‘hello‘]]
d        #[1, 2, 3, 0, [‘a‘, ‘b‘, ‘c‘]]

del d[0]
a        #[   0, 3, 4, [‘a‘, ‘b‘, ‘c‘, ‘hello‘], 5]
c        #[   2, 0, 4, [‘a‘, ‘b‘, ‘c‘, ‘hello‘]]
d        #[ 2, 3, 0, [‘a‘, ‘b‘, ‘c‘]]

# 2
del a[3][0]
a        #[   0, 3, 4, [ ‘b‘, ‘c‘, ‘hello‘], 5]
c        #[   2, 0, 4, [ ‘b‘, ‘c‘, ‘hello‘]]
d        #[   2, 3, 0, [‘a‘, ‘b‘, ‘c‘]]

简单点说[个人臆想,期待指正]

1. copy.copy 浅拷贝     -元素有的引用计数+1(如a的元素1,2,3,4),独立的;而有的则没有(如上面a的元素[‘a‘,‘b‘,‘c‘]),不是完全独立
2. copy.deepcopy 深拷贝  -元素或者引用计数+1,或者创建新对象,实现完全独立

#打印[‘a‘,‘b‘,‘c‘]地址
[id(x) for x in a[3]] #[1398793470232, 139879343471752, 139879314380720] [id(x) for x in c[3]] #[1398793470232, 139879343471752, 139879314380720] [id(x) for x in d[3]] #[1398793470192, 139879343470232, 139879343471752]

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。