python的浅拷贝和深拷贝

标签: 浅拷贝  深拷贝

浅拷贝:
拷贝了一份内存地址,即源数据的地址和拷贝数据的地址是一样的。如果修改的是数据不可变类型类型的,那么拷贝数据不会改变,如果修改的是数据是可变类型的,那么拷贝数据会被改变。

深拷贝:
相当于是拷贝了一个副本,内存的引用已经被改变,也就是新开辟了一个内存空间,因此,如果修改原数据时,是不会对拷贝数据造成任何影响的,拷贝数据的值是不会改变的。

一、引用

分别对a和b赋值,产生的是2个对象。

对c赋值,再把c赋值给d,产生的是一个对象,c和d都同时指向这一个对象。


>>> a = [1,2,3]
>>> b = [1,2,3]
>>> id(a)
2532421388296
>>> id(b)
2532421388168
>>> c = [1,2,3]
>>> d = c
>>> id(c)
2532421388872
>>> id(d)
2532421388872

二、浅拷贝和深拷贝

浅拷贝和深拷贝对于基本类型(intlongfloatboolstr等类型的数据来说,作用是一样的,都是拷贝一份全新的对象,改变原数据不会对拷贝的新数据产生任何的影响。

>>> a = [1,2,3]
>>> b = a  # a和b指向同一个引用,因此地址一样
>>> id(a)
2532421388872
>>> id(b)
2532421388872
>>> c = a.copy() # 浅拷贝,c是一个新的对象,因此地址与a、b的不同
>>> id(c)
2532421388808
>>> a.append(4)  # 修改a,不会对c造成影响
>>> a
[1, 2, 3, 4]
>>> b
[1, 2, 3, 4]
>>> c
[1, 2, 3]
>>> import copy
>>> d = copy.deepcopy(a)  # 深拷贝
>>> id(d)
2532421388552
>>> d
[1, 2, 3, 4]
>>> a.append(5)  # 修改a,不会对d造成影响
>>> a
[1, 2, 3, 4, 5]
>>> b
[1, 2, 3, 4, 5]
>>> c
[1, 2, 3]
>>> d
[1, 2, 3, 4]

但对于不是基础类型的数据来说,浅拷贝和深拷贝的作用就不一样了。浅拷贝不会直接拷贝对象进行重新存储,而是用引用的方式指向原来的值。而深拷贝会完完全全拷贝一份新的对象进行重新存储。

>>> dict1 = {'name':['zxf','jzz'],'age':15}
>>> dict2 = dict1
>>> id(dict1)
2532419004816
>>> id(dict2)
2532419004816
>>> dict3 = dict1.copy()  # 浅拷贝
>>> id(dict3)
2532419004888
>>> dict1['name']= 'hello'
>>> dict1
{'name': 'hello', 'age': 15}
>>> dict2
{'name': 'hello', 'age': 15}
>>> dict3
{'name': ['zxf', 'jzz'], 'age': 15}   # 修改dict1对dict3没有产生影响
>>> dict1['name'] = ['hello','world']
>>> dict1
{'name': ['hello', 'world'], 'age': 15}
>>> dict2
{'name': ['hello', 'world'], 'age': 15}
>>> dict3
{'name': ['zxf', 'jzz'], 'age': 15}
>>> dict1['name'].append('third')
>>> dict1
{'name': ['hello', 'world', 'third'], 'age': 15}
>>> dict2
{'name': ['hello', 'world', 'third'], 'age': 15}
>>> dict3
{'name': ['zxf', 'jzz'], 'age': 15}
>>> dict3.copy()
{'name': ['zxf', 'jzz'], 'age': 15}
>>> dict3 = dict1.copy()
>>> dict3
{'name': ['hello', 'world', 'third'], 'age': 15}
>>> dict1['name'].append('first')
>>> dict1
{'name': ['hello', 'world', 'third', 'first'], 'age': 15}
>>> dict2
{'name': ['hello', 'world', 'third', 'first'], 'age': 15}
>>> dict3
{'name': ['hello', 'world', 'third', 'first'], 'age': 15}   # 同样是浅拷贝,但是这次修改dict1对dict3产生了影响
>>> dict4 = copy.deepcopy(dict1)
>>> dict4
{'name': ['hello', 'world', 'third', 'first'], 'age': 15}
>>> dict1['name'].append('second')
>>> dict1
{'name': ['hello', 'world', 'third', 'first', 'second'], 'age': 15}
>>> dict2
{'name': ['hello', 'world', 'third', 'first', 'second'], 'age': 15}
>>> dict3
{'name': ['hello', 'world', 'third', 'first', 'second'], 'age': 15}
>>> dict4
{'name': ['hello', 'world', 'third', 'first'], 'age': 15}  # 深拷贝,修改dict1对dict4没有产生影响

从上述代码可以看出,字典的值是列表,python不会在被复制的那个对象中重新存储,而是用引用的方式,指向原来的那个列表,因此在修改列表的时候,会影响到被复制的那个对象。


三、补充

字符串和数值是没有copy()操作的

'str'/’int’ object has no attribute 'copy'

版权声明:本文为loner_fang原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/loner_fang/article/details/80641293