python的拷贝一般有三个方法:

直接赋值

浅拷贝

深拷贝

直接赋值

顾名思义,把一个变量赋值给另一个变量,上代码:

In [1]: a=[1,2,3]In [2]: b=aIn [3]: id(a)  #在内存中的地址Out[3]: 2594082675264In [4]: id(b) #a和b占用同一个内存Out[4]: 2594082675264In [5]: a.append(4)In [6]: aOut[6]: [1, 2, 3, 4]In [7]: bOut[7]: [1, 2, 3, 4]

我们发现通过b=a这种形式赋值深拷贝浅拷贝,两个变量的id()函数值是一样的,即两个变量占用同一个内存地址,相当于b只是a的一个别名,当修改a的值时,b也会跟着一起变。

2. 浅拷贝

浅拷贝是使用copy库的copy()方法进行拷贝,且看代码:

js深拷贝浅拷贝_深拷贝浅拷贝_深拷贝和浅拷贝的区别

In [8]:  import copyIn [9]: a=10In [10]: b=copy.copy(a)In [11]:  id(a)Out[11]: 140730619471952In [12]: id(b)Out[12]: 140730619471952In [13]: a1='这是一个字符串'In [14]: b1=copy.copy(a1)In [15]: id(a1)Out[15]: 2594085680496In [16]: id(b1)Out[16]: 2594085680496In [17]: a2=(3,6,9)In [18]: b2=copy.copy(a2)In [19]: id(a2)Out[19]: 2594085623040In [20]: id(b2)Out[20]: 2594085623040

我们发现当浅拷贝对象是数值、字符串和元组等不可变类型时,copy.copy()函数只拷贝地址空间,不开辟新的地址空间。所以对于这三种不可变类型的变量而言,浅拷贝只是起个别名而已,而且它们是不可变类型,不存在修改后别名变量值变不变的问题。

再看:

In [36]: a4=[666,888]In [37]: b4=copy.copy(a4)In [38]: id(a4)Out[38]: 2594085696064In [39]: id(b4)Out[39]: 2594085766912In [40]: a4.append(999)In [41]: a4Out[41]: [666, 888, 999]In [42]: b4Out[42]: [666, 888]

当浅拷贝对象是列表、字典和集合等可变类型时,copy.copy()函数会开辟新的存储空间来存储拷贝对象,当原变量的值改变时,拷贝变量的值不会变。

3.深拷贝

深拷贝是使用copy库的deepcopy()方法进行拷贝,代码如下:

In [21]: a1=[2,3,4]In [22]: b1=copy.deepcopy(a1)In [23]: id(a1)Out[23]: 2594082796928In [24]: id(b1)Out[24]: 2594085748416In [25]: a2={'元宵节':'正月十五','端午节':'五月初五','中秋节':'八月十五'}In [26]: b2=copy.deepcopy(a2)In [27]: id(a2)Out[27]: 2594085793664In [28]: id(b2)Out[28]: 2594082725056In [29]: a3={'北京','上海','广州'}In [30]: b3=copy.deepcopy(a3)In [31]: id(a3)Out[31]: 2594083778112In [32]: id(b3)Out[32]: 2594083777440In [33]: a1.append(666)In [34]: a1Out[34]: [234666]In [35]: b1Out[35]: [2, 3, 4]

深拷贝浅拷贝_深拷贝和浅拷贝的区别_js深拷贝浅拷贝

很容易看出来,当深拷贝对象是列表、字典和集合等可变类型时,deepcopy()函数会开辟一个新的地址空间来存储拷贝变量。当原变量的值改变时,拷贝变量的值不会改变。

如果深拷贝对象是不可变类型呢?同样是

In [51]: a='OK'In [52]: b=copy.deepcopy(a)In [53]: id(a)Out[53]: 2593981224112In [54]: id(b)Out[54]: 2593981224112In [55]: a="OK!"In [56]: aOut[56]: 'OK!'In [57]: bOut[57]: 'OK'In [58]: id(a)Out[58]: 2594082723952In [59]: id(b)Out[59]: 2593981224112

对于字符串等不可变类型来说,深拷贝也不会创建一个新的存储单元。但这里有一个问题,因为字符串是不可变类型,当对变量a重新赋值时,相当于变量a存储的字符串变了,指向的存储单元也变了。

js深拷贝浅拷贝_深拷贝和浅拷贝的区别_深拷贝浅拷贝

总结一下:

1. 列表、字典和集合是可变类型深拷贝浅拷贝,数值、元组和字符串是不可变类型;

2. 直接赋值只是起一个别名,不开辟新的存储空间;

3. 浅拷贝对不可变类型不开辟新的地址空间,对可变类型开辟新的地址空间;

4. 深拷贝对可变类型的变量开辟新的地址空间,对不可变类型的变量不开辟新的地址空间,但对变量重新赋值时,变量指向的存储空间会发生改变。

深拷贝和浅拷贝的区别是python程序员面试最常见的问题之一,望有兴趣的同学们多多复习,加深理解!