浅拷贝 深拷贝

1. 浅拷贝:只拷贝第一层,更深层的还指向原有的内存地址。

2. 深拷贝: 递归拷贝多层。

1. 先看一例子:

import copy

a = [1, 3, 4]

f = a
print(id(a))
print(id(f))

G:envsflaskenvScriptspython.exe G:/workspace/albumy-master/11.py
1841649924552
1841649924552

将变量a 赋值给变脸f,其实是将变量f 指向变量a对应值得内存地址。

 

浅拷贝:

import copy

a = [1, 3, 4]
b = [2, 5]
c = [a, b]
d = copy.copy(c)
print('c的内存地址', id(c))
print('d的内存地址', id(d))
print('c的第一个元素内存地址', id(c[0]))
print('d的第一个元素内存地址', id(d[0]))

G:envsflaskenvScriptspython.exe G:/workspace/albumy-master/11.py
c的内存地址 1507477928264
d的内存地址 1507478038024
c的第一个元素内存地址 1507477928392
d的第一个元素内存地址 1507477928392

d元素是经过浅拷贝c元素得来的,因此d元素的内存地址与c元素的内存地址不相同,就是拷贝了一份c的元素在内存中重新开辟一段空间存储,但是浅拷贝不拷贝内层的引用。因此

c元素的第一个元素值得内存地址与d元素的一个元素值得内存地址相同。

深拷贝:

import copy

a = [1, 3, 4]
b = [2, 5]
c = [a, b]
e = copy.deepcopy(c)
print('c的内存地址', id(c))
print('e的内存地址', id(e))
print('c的第一个元素内存地址', id(c[0]))
print('e的第一个元素内存地址', id(e[0]))

G:envsflaskenvScriptspython.exe G:/workspace/albumy-master/11.py
c的内存地址 2093738014856
e的内存地址 2093738015048
c的第一个元素内存地址 2093738014984
e的第一个元素内存地址 2093738014024

可以看出,深拷贝内层元素的值也被重新拷贝一份,而不是执行原来的引用。

对于元组的拷贝

import copy


a = (1, 3, 4)
b = copy.copy(a)
print(id(a))
print(id(b))

G:envsflaskenvScriptspython.exe G:/workspace/albumy-master/11.py
1950885994784
1950885994784

因为元祖是不可变类型,那么久意味着数据一定不能修改,因此使用浅拷贝时,它会自动判断,如果是元祖,就直接指向,不会重新拷贝一份。

如果是深拷贝呢

import copy


a = (1, 3, 4)
b = copy.deepcopy(a)
print(id(a))
print(id(b))

G:envsflaskenvScriptspython.exe G:/workspace/albumy-master/11.py
2048102687008
2048102687008

还是直接指向。

再看例子

import copy


a = [1, 3, 4]
b = [2, 5]
c = (a, b)
d = copy.copy(c)
print(id(c))
print(id(d))
print(id(c[0]))
print(id(d[0]))

G:envsflaskenvScriptspython.exe G:/workspace/albumy-master/11.py
1698151178632
1698151178632
1698152560328
1698152560328

结论,对于元祖的浅拷贝,即使元祖中存在可变元素 如列表,也都是指向。

那么深拷贝呢

import copy


a = [1, 3, 4]
b = [2, 5]
c = (a, b)
d = copy.deepcopy(c)
print(id(c))
print(id(d))
print(id(c[0]))
print(id(d[0]))

G:envsflaskenvScriptspython.exe G:/workspace/albumy-master/11.py
2626026493576
2626026495560
2626026321992
2626026322056

结论; 对于深拷贝,若元祖中存在可变元素,那么深拷贝就会重新拷贝一份。

那么总结一个元祖的拷贝:

如果用浅拷贝 深拷贝对一个全部都是不可变类型的数据进行拷贝,那么他们的结果相同,都是指向引用。

如果拷贝的是一个不可变类型的数据,但是内层存在可变类型时,浅拷贝是指向引用,深拷贝是重新拷贝一份。

其他的操作也是拷贝(列表的切片,是浅拷贝)

 字典的拷贝

先说一下字段的存储原理,创建一个字典时,字典的key在字典中存储,但是对应的值存储的是值对应的引用。

所以说,对于字典的浅拷贝,拷贝出来的字典的值,也是执行引用。

import copy


a = {'k1': 'v1', 'k2': 'v2', 'k3': [1, 3, 5]}
b = copy.copy(a)
print(id(a))
print(id(b))
a['k3'].append(9)
print(a)
print(b)

G:envsflaskenvScriptspython.exe G:/workspace/albumy-master/11.py
2245390036616
2245396227592
{'k2': 'v2', 'k3': [1, 3, 5, 9], 'k1': 'v1'}
{'k2': 'v2', 'k3': [1, 3, 5, 9], 'k1': 'v1'}

深拷贝

import copy


a = {'k1': 'v1', 'k2': 'v2', 'k3': [1, 3, 5]}
b = copy.deepcopy(a)
print(id(a))
print(id(b))
a['k3'].append(9)
print(a)
print(b)

G:envsflaskenvScriptspython.exe G:/workspace/albumy-master/11.py
2422065983112
2422068394568
{'k1': 'v1', 'k2': 'v2', 'k3': [1, 3, 5, 9]}
{'k1': 'v1', 'k2': 'v2', 'k3': [1, 3, 5]}

原文地址:https://www.cnblogs.com/yuqiangli0616/p/10291252.html