python基础拾遗002--深拷贝和浅拷贝

在比较深拷贝和浅拷贝之前,要先理解python的可变类型的变量和不可变类型的变量。

python中数字,字符串,元组就是典型的不可变类型的变量。对于不可变类型的变量,改变它们的值其实就是在内存中新建了一个变量。如:

>>> a=120;b="ACS";c=(11,22,23);print(id(a),id(b),id(c))
10923232 140086869042264 140086868265720
>>> a+=120;b=b+"ACA";c=(11,22,21,21);print(id(a),id(b),id(c))
10927072 140086899703008 140086899571352
>>> a,b,c
(240, 'ACSACA', (11, 22, 21, 21))

注意,元组是不可变类型的变量,但是如果元组里的元素是可变类型则可以改变。如:

元组 a=(12,'ABC',[12,13,14],(‘a’,'b')] a[0]是一个数字不可以修改,a[1]是字符串也不可以修改,a[2]是列表,可以对列表做修改。其实所谓元组不可以修改,可以理解成不能改变每个元素指向的变量的引用值。

>>> a=(12,'ABC',[12,13,14],('a','b'))
>>> a[0]=13
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> a[1]='abc'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> a[2].append(15)
>>> a
(12, 'ABC', [12, 13, 14, 15], ('a', 'b'))
>>> a[2]=[12,13,21,21,21]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> a[3]=('a','c')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

深拷贝和浅拷贝:可以把浅拷贝理解成不彻底的拷贝。而深拷贝则是完全互相不相干的变量,在内存中各自拥有独立的空间。

copy.copy(变量)-->浅拷贝 copy.deepcopy(变量)->深拷贝

对于不可变类型的数字和字符串,深拷贝和浅拷贝没有什么区别。

>>> a=123.123
>>> b=copy.copy(a)
>>> b is a
True
>>> c=copy.deepcopy(a)
>>> c is a
True
>>> a=12.12
>>> b
123.123
>>> c
123.123
>>> m='ABC'
>>> n=copy.copy(m)
>>> n is m
True
>>> s=copy.deepcopy(m)
>>> s is m
True
>>> m='ABCCBDA'
>>> n
'ABC'
>>> s
'ABC'

但是对于元组,情况有点特殊。因为元组里面可能会存储可变类型的变量,例如列表或者字典。

当元组里面只存储了数字和字符串这两种不可变类型的变量,copy和deepcopy没有什么区别。反正这时候的元组是完全不可改变的。

>>> m=(11,22,'AA')
>>> n=copy.copy(m)
>>> t=copy.deepcopy(m)
>>> m is n
True
>>> m is t
True

当元组里面存储了可变类型的变量,copy和deepcopy就不一样了。is 可以判断这两个变量的内存地址是否一样。如下: a和b指向同一块内存地址,但是c是另外一块。

>>> a=(12,'AA',[11,22,33])
>>> b=copy.copy(a)
>>> c=copy.deepcopy(a)
>>> b is a
True
>>> c is a
False
>>> a[2].extend([44,55])
>>> a
(12, 'AA', [11, 22, 33, 44, 55])
>>> b
(12, 'AA', [11, 22, 33, 44, 55])
>>> c
(12, 'AA', [11, 22, 33])

下面再看一下更复杂的情况,当元组里面放的是元组的时候。

>>> m=(11,'A',('a','b'))
>>> n=copy.copy(m)
>>> s=copy.deepcopy(m)
>>> m is n
True
>>> m is s
True
>>> q=(11,'A',('a',('a',[11,12])))
>>> r=copy.deepcopy(q)
>>> t=copy.copy(q)
>>> q is t
True
>>> r is t
False

所以在理解深拷贝和浅拷贝的不同之处之前,我们一定要理解python里面可变类型和不可变类型,尤其是对于元组,可以理解只有当元组里面存储的只有数字或者字符串的时候,它才是真正意义上的不可变类型。最简单的理解就是给你一个元组,这个元组里的值再也不可能改变,那么它的深拷贝和浅拷贝就完全一样了。

真正不可变的元组: (11,23,‘A’) 

                                  (11,23,(11,23,'A'))

                                  (11,23,(11,23,('a','b','c')))

值有可能改变的元组: ('a',11,[11,12,13])

                                   ('a',11,(11,23,23,[12,21,21]))

下面我们再来讨论一下可变类型的深拷贝和浅拷贝:(以列表为例)

和之前讨论元组类似,对于列表中的不可变元素,浅拷贝完全拷贝了一份新的值,对于可变类型的元素,浅拷贝拷贝该元素的引用,内存中其实还是只存了一份值。只是这里要注意,可变类型的元素包括上面讲的元素值可以改变的元组。对于可变类型的变量,无论深拷贝和浅拷贝都会在内存中开辟一个新的内存空间出来。

>>> import copy
>>> a=[12,'abc',(12,23,34),(12,23,[12,23,24])]
>>> b=copy.copy(a)
>>> c=copy.deepcopy(a)
>>> a is b
False
>>> a is c
False
>>> a[0]=122
>>> a[1]='abcd'
>>> a[2]=(12,23,21,11,21)
>>> a[3][2].append('111')
>>> a
[122, 'abcd', (12, 23, 21, 11, 21), (12, 23, [12, 23, 24, '111'])]
>>> b
[12, 'abc', (12, 23, 34), (12, 23, [12, 23, 24, '111'])]
>>> c
[12, 'abc', (12, 23, 34), (12, 23, [12, 23, 24])]

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值