python中的完全拷贝_Python 深拷贝与浅拷贝详解

ae2cd9024f7eaffce276664ad692af81.png

要说清楚Python中的深浅拷贝,需要搞清楚下面一系列概念:

变量-引用-对象(可变对象,不可变对象)-切片-拷贝(浅拷贝,深拷贝)

在Python中一切都是对象

4dc4ac01deb02b5b554cf236bd3cfd8b.png

甚至连type其本身都是对象,type对象

Python中变量与C/C++/Java中不同,它是指对象的引用,Python是动态类型,程序运行时候,会根据对象的类型来确认变量到底是什么类型。

单独赋值:比如说:

>>> a = 3

在运行a=3后,变量a变成了对象3的一个引用。在内部,变量事实上是到对象内存空间的一个指针

0f09e2e238f1c6343eeab92b0e46ed5a.png

因为Python的变量不过是对象的引用,或指向对象的指针,因此在程序中可以经常改变变量引用

代码如下:

>>> x = 42 #变量绑定到整型对象

>>> x = "Hello" #现在又成了字符串

>>> x = [1,2,3] #现在又成了列表

专业表述如下:

* 变量是一个系统表的元素,拥有指向对象的连接的空间

* 对象是被分配的一块内存,存储其所代表的值

* 引用是自动形成的从变量到对象的指针

* 特别注意: 类型属于对象,不是变量

比如像刚才的a=3, 整数对象3包含了两重信息

1.值为3

2.一个头部信息:告诉Pthyon,这是个整数对象[相当于一个指向int的指针]

共享引用: 比如说:

代码如下:

>>> a = 3

>>> b = a

在运行赋值语句b = a之后,变量a和变量b指向了同一个对象的内存空间.

5ae1843cbbef16f3ef0d86d1d1413377.png

5e8a5c6325a51385a966b802dea99563.png

从上图可以看到,a和b,其id完全一样,指向同一个整数对象3,或者说同一块内存

15a59959ce5f90cca00278eb3ca2fb3b.png

如果删掉a后, 不会影响b

679b5318df05fefd24d86626af23a1f3.png

拷贝概念的引入就是针对:可变对象的共享引用潜在的副作用而提出的.

【可变对象-不可变对象】

在Python中不可变对象指:一旦创建就不可修改的对象,包括字符串,元祖,数字

在Python中可变对象是指:可以修改的对象,包括:列表、字典

上面说的a,b都是整数,整数是不可变对象,如果是可变对象的话,就是另外一回事了。

代码如下:

>>> L1 = [2,3,4] #L1变量指向的是一个可变对象:列表

>>> L2 = L1 #将L1值赋给L2后,两者共享引用同一个列表对象[1,2,3,4]

>>> L1[0] = 200 #因为列表可变,改变L1中第一个元素的值

>>> L1; L2 #改变后,L1,L2同时改变,因为对象本身值变了

[200, 3, 4]

[200, 3, 4]

如果不想改变列表L2的值,有两种方法:切片 和 copy模块

代码如下:

>>> L1 = [2,3,4]

>>> L2 = L1

>>> id(L1);id(L2) #共享引用一个可变对象

45811784L

45811784L

>>> L2 = L1[:] #切片操作

>>> id(L1);id(L2) #切片后,对象就不一样了

45811784L

45806920L

>>> L1[0] = 200

>>> L1;L2 #L1发生改变,L2没有变化

[200, 3, 4]

[2, 3, 4]

【拷贝】

切片技术应用于所有的序列,包括:列表、字符串、元祖

但切片不能应用于字典。对字典只能使用D.copy()方法或D.deepcopy()方法.

1cbf8baf4ee14e99957e4b3c8d1a149a.png

深浅拷贝,即可用于序列,也可用于字典

代码如下:

>>> import copy

>>> X = copy.copy(Y) #浅拷贝:只拷贝顶级的对象,或者说:父级对象

>>> X = copy.deepcopy(Y) #深拷贝:拷贝所有对象,顶级对象及其嵌套对象。或者说:父级对象及其子对象

如果字典只有顶级对象:

e75e28b0be7f0ef012bb6832c6b7f72f.png

如果字典中嵌套对象:

acddb37e1b40eb0019c185bbc3db5732.png

【结论】

深浅拷贝都是对源对象的复制,占用不同的内存空间

如果源对象只有一级目录的话,源做任何改动,不影响深浅拷贝对象

如果源对象不止一级目录的话,源做任何改动,都要影响浅拷贝,但不影响深拷贝

序列对象的切片其实是浅拷贝,即只拷贝顶级的对象

直接赋值:其实就是对象的引用(别名)。

浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的子对象。

深拷贝(deepcopy): copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值