Python对象的赋值和拷贝

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liuweiyuxiang/article/details/89350481

0 前言

前面讲了python的可变对象和不可变对象,总结起来就是,可变对象指向的内存中的值可以修改,不可变对象指向的内存的中的值不可以修改,如果想改变这个对象的值,会重新申请一个内存地址,修改值后存到新的地址上,然后另对象指向新的内存地址。关于可变对象和不可变对象的内容可以参考博客.
这篇我们来看一下对象的深浅拷贝,主要是针对可变对象,对于不可变对象,修改了对象的值,就会重新分配地址,对原来对象地址的内容不会有影响。但是tuple里放list的情况,有些特殊,我们最后做一下探究。

1 赋值和拷贝

python对对象进行复制一般有三种方法,下面我们逐个来看

1.1 对象赋值

直接赋值:默认浅拷贝传递对象的引用而已,原始列表改变,被赋值的b也会做相同的改变。
在python中,对象赋值实际上是对象的引用。 当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用。

>>> alist = [1, 2, 3, ['a', 'b']]
>>> b=alist
>>> print b
[1, 2, 3, ['a', 'b']]
>>> alist.append(5)
>>> print alist;print b
[1, 2, 3, ['a', 'b'], 5]
[1, 2, 3, ['a', 'b'], 5]

在这里插入图片描述

1.2 浅拷贝

浅拷贝其实存在两种方式,一种是使用copy模块的copy函数,一种是使用[:]
copy浅拷贝:拷贝当前对象,但是如果当前对象存在子对象的话,没有拷贝子对象,所以改变新对象的子对象,原始数据的子对象也会改变。

>>> import copy
>>> alist = [1, 2, 3, ['a', 'b']]
>>> c=copy.copy(alist)
>>> print alist;print c
[1, 2, 3, ['a', 'b']]
[1, 2, 3, ['a', 'b']]
>>> alist.append(5)
>>> print alist;print c
[1, 2, 3, ['a', 'b'], 5]
[1, 2, 3, ['a', 'b']]

>>> alist[3]
['a', 'b']
>>> alist[3].append('cccc')
>>> print alist;print c
[1, 2, 3, ['a', 'b', 'cccc'], 5]
[1, 2, 3, ['a', 'b', 'cccc']] #里面的子对象被改变了

在这里插入图片描述[:]浅拷贝: 这种方式和使用copy()等价,也是不拷贝子对象。

>>> alist = [1, 2, 3, ['a', 'b']]
>>> c=alist[:]

1.3 deepcopy()深拷贝

包含对象里面的子对象的拷贝,所以原始对象的改变不会造成深拷贝里任何子元素的改变。拷贝完成后两个对象相互独立。

>>> import copy
>>> alist = [1, 2, 3, ['a', 'b']]
>>> d=copy.deepcopy(alist)
>>> print alist;print d
[1, 2, 3, ['a', 'b']]
[1, 2, 3, ['a', 'b']] #始终没有改变
>>> alist.append(5)
>>> print alist;print d
[1, 2, 3, ['a', 'b'], 5]
[1, 2, 3, ['a', 'b']] #始终没有改变
>>> alist[3]
['a', 'b']
>>> alist[3].append("ccccc")
>>> print alist;print d
[1, 2, 3, ['a', 'b', 'ccccc'], 5]
[1, 2, 3, ['a', 'b']]   #始终没有改变

在这里插入图片描述

2 tuple里使用list

tuple 是不可变对象,但是list是可变对象,我们可以修改,tuple中list的内容;我们来看一下对含有list的tuple来进行复制时的情况。
首先是,赋值是一样,同时是复制引用。
使用copy函数就会存在一些不一样的情况了:

>>> a = tuple([1,2,[1,2,3]])
>>> c = a[:]
>>> d = copy.copy(a)
>>> d[2].append(4)
>>> a
(1, 2, [1, 2, 3, 4])
>>> d
(1, 2, [1, 2, 3, 4])
#我看来看a,c,d的id
>>> id(a)
57247712
>>> id(c)
57247712
>>> id(d)
57247712

我们使用c[:]copy(a)并没有新的对象,他们的id都是相同的,但是对于list这类可变对象是会产生新的对象的。
接下来我们看看使用deepcopy会怎么样:

>>> a = tuple([1,2,[1,2,3]])
>>> e = copy.deepcopy(a)
>>> a
(1, 2, [1, 2, 3])
>>> e
(1, 2, [1, 2, 3, 4])
>>> id(a)
51611616
>>> id(e)
51609816

可以发现使用deepcopy产生了新的对象,并且对子对象进行了拷贝。
但是如果tuple没有可变对象的话,即使使用了deepcopy也不会产生新的对象。

>>> a = tuple([1,2,3])
>>> e = copy.deepcopy(a)
>>> id(a)
51526608
>>> id(e)
51526608

** 需要注意的就是:**

  1. 对于tuple含有list的情况: c[:]copy(a)并没有新的对象,他们的id都是相同的。
  2. 对于不可变的对象,就是使用deepcopy也不会产生新的对象。

参考文章:python的复制,深拷贝和浅拷贝的区别

猜你喜欢

转载自blog.csdn.net/liuweiyuxiang/article/details/89350481