直接赋值: 创建一个别名,本质上是对象引用。
浅拷贝: 拷贝父对象,而不会拷贝父对象内部的子对象。操作上,重新分配一块内存用于创建父对象,内部包含子对象的引用。
深拷贝: 完全拷贝父对象和子对象。新对象与原对象不再有关系。
此处引用 时代&信念 的博文内容。
浅拷贝:
父对象数据类型 | 子对象数据类型 | 父对象地址 | 子对象地址 |
---|---|---|---|
可变 | 可变 | 改变 | 相同 |
可变 | 不可变 | 改变 | 相同 |
不可变 | 可变 | 相同 | 相同 |
不可变 | 不可变 | 相同 | 相同 |
结论: 使用浅拷贝时,子对象相同;如果父对象为可变数据类型,则父对象不同,如果父对象为不可变数据类型,则父对象相同。
深拷贝:
父对象数据类型 | 子对象数据类型 | 父对象地址 | 子对象地址 |
---|---|---|---|
可变 | 可变 | 改变 | 改变 |
可变 | 不可变 | 改变 | 相同 |
不可变 | 可变 | 改变 | 改变 |
不可变 | 不可变 | 相同 | 相同 |
结论: 使用深拷贝时,如果子对象为可变数据类型,父对象和子对象都不同;如果子对象为不可变类型,子对象相同,父对象根据父对象的数据类型而定。
import copy
a = [1, ['a', 'b']]
b = a
c = a.copy()
d = copy.deepcopy(a)
print(a is b)
print(a is c)
print(a is d)
print(a[0] is b[0])
print(a[0] is c[0])
print(a[0] is d[0])
a.append(5) # 增加父对象中的元素
print(a)
print(b)
print(c)
print(d)
a[0] = 6 # 修改父对象中的元素
print(a)
print(b)
print(c)
print(d)
a[1].append('c') # 增加子对象中的元素
print(a)
print(b)
print(c)
print(d)
''' 输出结果 '''
True # b和a指向同一个父对象
False # c、d与a指向不同的父对象
False
True
True # a、c指向相同的子对象
False
[1, ['a', 'b'], 5]
[1, ['a', 'b'], 5]
[1, ['a', 'b']]
[1, ['a', 'b']]
[6, ['a', 'b'], 5] # a[0]指向新的子对象
[6, ['a', 'b'], 5]
[1, ['a', 'b']] # c[0]仍指向原来的子对象
[1, ['a', 'b']]
[6, ['a', 'b', 'c'], 5]
[6, ['a', 'b', 'c'], 5]
[1, ['a', 'b', 'c']] # c和a的子对象相同
[1, ['a', 'b']]
注意: 在Python中,根本没有办法删除值。 使用
del
只能删除对象名称。当一个值(放在内存空间)没有对象名称与之关联时,Python解释器会直接将其删掉,称为 “垃圾收集”。
x = 1
y = x
z = x
x += 1 # x指向新的值
del y # 删除变量名y
print(x, z) # z指向的值(内存空间)还在原位
print(y)
''' 输出结果 '''
2 1
Traceback (most recent call last):
File "/home/.../test.py", line 7, in <module>
print(y)
NameError: name 'y' is not defined
菜鸟教程. Python 直接赋值、浅拷贝和深度拷贝解析.
xzw96. Python 深拷贝和浅拷贝详解. CSDN博客.
时代&信念. Python中的浅拷贝和深拷贝(一看就懂!!!). CSDN博客.