简介
最直观的理解就是:
1.深拷贝,拷贝的程度深,自己新开辟了一块内存,将被拷贝内容全部拷贝过来了;
2.浅拷贝,拷贝的程度浅,只拷贝原数据的首地址,然后通过原数据的首地址,去获取内容。
两者的优缺点对比:
(1)深拷贝拷贝程度高,将原数据复制到新的内存空间中。改变拷贝后的内容不影响原数据内容。但是深拷贝耗时长,且占用内存空间。
(2)浅拷贝拷贝程度低,只复制原数据的地址。其实是将副本的地址指向原数据地址。修改副本内容,是通过当前地址指向原数据地址,去修改。所以修改副本内容会影响到原数据内容。但是浅拷贝耗时短,占用内存空间少。
浅拷贝
有一层数据类型,且数据类型时可变数据类型,例如:列表、字典
import copy
a = [1,2,3]
b = copy.copy(a)
print(a)
# [1, 2, 3]
print(b)
# [1, 2, 3]
# 地址不一致
print(id(a))
# 1579517559496
print(id(b))
# 1579517560200
a.append(4)
print(a)
# [1, 2, 3, 4]
print(b)
# [1, 2, 3]
有一层数据类型,且数据类型时不可变数据类型,例如:元组、字符串
import copy
a = (6,7,8)
b = copy.copy(a)
print(a)
# (6, 7, 8)
print(b)
# (6, 7, 8)
# 地址一致
print(id(a))
# 2593238617544
print(id(b))
# 2593238617544
有两层数据类型,外层为可变数据类型,内层为可变数据类型
import copy
a = [1,2]
b = [3,4]
c = [a,b]
d = copy.copy(c)
print(c)
[[1, 2], [3, 4]]
print(d)
[[1, 2], [3, 4]]
print(id(c))
# 2280002580808
# 外层地址改变
print(id(d))
# 2280002580744
print(id(a))
# 2280002580936
print(id(b))
# 2280002581768
# 内层地址不变
print(id(c[0]))
# 2280002580936
print(id(c[1]))
# 2280002581768
print(id(d[0]))
# 2280002580936
print(id(d[1]))
# 2280002581768
有两层数据类型,外层为可变数据类型,内层为不可变数据类型
import copy
a = (7,8)
b = (9,0)
c = [a,b]
d = copy.copy(c)
print(c)
# [(7, 8), (9, 0)]
print(d)
# [(7, 8), (9, 0)]
print(id(a))
# 2064778398344
print(id(b))
# 2064778398472
print(id(c))
# 2064778597512
# 外层地址改变
print(id(d))
# 2064778598856
# 内层地址不变
print(id(c[0]))
# 2064778398344
print(id(d[0]))
# 2064778398344
print(id(c[1]))
# 2064778398472
print(id(d[1]))
# 2064778398472
有两层数据类型,外层为不可变数据类型,内层为不可变数据类型
import copy
a = (1,2)
b = (3,4)
c = (a,b)
d = copy.copy(c)
print(c)
# ((1, 2), (3, 4))
print(d)
# ((1, 2), (3, 4))
print(id(a))
# 1933760334536
print(id(b))
# 1933760334664
# 外层地址不变
print(id(c))
# 1933760521736
print(id(d))
# 1933760521736
# 内层地址不变
print(id(c[0]))
# 1933760334536
print(id(c[1]))
# 1933760334664
print(id(d[0]))
# 1933760334536
print(id(d[1]))
# 1933760334664
有两层数据类型,外层为不可变数据类型,内层为可变数据类型
import copy
a = [1,2]
b = [3,4]
c = (a,b)
d = copy.copy(c)
print(c)
# ([1, 2], [3, 4])
print(d)
# ([1, 2], [3, 4])
print(id(a))
# 2098312709128
print(id(b))
# 2098312709960
# 外层地址不变
print(id(c))
# 2098312709512
print(id(d))
# 2098312709512
# 内层地址不变
print(id(c[0]))
# 2098312709128
print(id(c[1]))
# 2098312709960
print(id(d[0]))
# 2098312709128
print(id(d[1]))
# 2098312709960
深拷贝
有一层数据类型,且数据类型时可变数据类型,例如:列表、字典
import copy
a = [1,2]
b = copy.deepcopy(a)
print(a)
# [1, 2]
print(b)
# [1, 2]
# 地址发生改变
print(id(a))
# 2712262157064
print(id(b))
# 2712262157832
有一层数据类型,且数据类型时不可变数据类型,例如:元组、字符串
import copy
a = (1,2)
b = copy.deepcopy(a)
print(a)
# (1, 2)
print(b)
# (1, 2)
# 地址未改变
print(id(a))
# 2372779051400
print(id(b))
# 2372779051400
有两层数据类型,外层为可变数据类型,内层为可变数据类型
import copy
a = [1,2]
b = [3,4]
c = [a,b]
d = copy.deepcopy(c)
print(c)
# [[1, 2], [3, 4]]
print(d)
# [[1, 2], [3, 4]]
print(id(a))
# 2044073358024
print(id(b))
# 2044073358984
# 外层地址不变
print(id(c))
# 2044073357896
print(id(d))
# 2044073358856
# 内层地址改变
print(id(c[0]))
# 2044073358024
print(id(c[1]))
# 2044073358984
print(id(d[0]))
# 2044073357832
print(id(d[1]))
# 2044072936328
有两层数据类型,外层为可变数据类型,内层为不可变数据类型
import copy
a = (1,2)
b = (3,4)
c = [a,b]
d = copy.deepcopy(c)
print(c)
# [(1, 2), (3, 4)]
print(d)
# [(1, 2), (3, 4)]
print(id(a))
# 2197363967752
print(id(b))
# 2197363967880
# 外层地址改变
print(id(c))
# 2197364167112
print(id(d))
# 2197364168520
# 内层地址不变
print(id(c[0]))
# 2197363967752
print(id(c[1]))
# 2197363967880
print(id(d[0]))
# 2197363967752
print(id(d[1]))
# 2197363967880
有两层数据类型,外层为不可变数据类型,内层为不可变数据类型
import copy
a = (1,2)
b = (3,4)
c = (a,b)
d = copy.deepcopy(c)
print(c)
# ((1, 2), (3, 4))
print(d)
# ((1, 2), (3, 4))
print(id(a))
# 2582331737992
print(id(b))
# 2582331738120
# 外层地址不变
print(id(c))
# 2582331942280
print(id(d))
# 2582331942280
# 内层地址不变
print(id(c[0]))
# 2582331737992
print(id(c[1]))
# 2582331738120
print(id(d[0]))
# 2582331737992
print(id(d[1]))
# 2582331738120
有两层数据类型,外层为不可变数据类型,内层为可变数据类型
import copy
a = [1,2]
b = [3,4]
c = (a,b)
d = copy.deepcopy(c)
print(c)
# ([1, 2], [3, 4])
print(d)
# ([1, 2], [3, 4])
print(id(a))
# 1404187259528
print(id(b))
# 1404187260424
# 外层地址改变
print(id(c))
# 1404187259976
print(id(d))
# 1404187259784
# 内层地址改变
print(id(c[0]))
# 1404187259528
print(id(c[1]))
# 1404187260424
print(id(d[0]))
# 1404187259336
print(id(d[1]))
# 1404187059400
总结
浅拷贝:
一层,可变: 地址不一致
一层,不可变: 地址一致
两层,外可变,内可变: 外层不一致,内层一致
两层,外可变,内不可变: 外层不一致,内层一致
两层,外不可变,内不可变: 外层一致,内层一致
两层,外不可变,内可变: 外层一致,内层一致
深拷贝:
一层,可变:地址不一致
一层,不可变:地址一致
两层,外可变,内可变:外层一致,内层不一致
两层,外可变,内不可变:外层不一致,内层一致
两层,外不可变,内不可变:外层一致,内层一致
两层,外不可变,内可变:外层不一致,内层不一致
浅拷贝,指的是重新分配一块内存,创建一个新的对象,但里面的元素是原对象中各个子对象的引用。
深拷贝,是指重新分配一块内存,创建一个新的对象,并且将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中。因此,新对象和原对象没有任何关联。
当内层为可变数据类型时,深拷贝后内层外层地址均发生改变。当内层为不可变数据类型时,外层不管是可变还是不可变数据类型,使用深拷贝,都不会改变内层地址,只会改变外层地址。
使用浅拷贝是只能在外层数据类型为可变数据类型时,才能改变外层地址。而内层地址,无论是否为可变数据类型还是不可变数据类型,使用浅拷贝都不会改变内层数据类型地址。