Python 直接赋值、浅拷贝和深度拷贝解析
1. 直接赋值
在Python中,对象赋值实际上是对象的引用。当创建一个对象,然后把它赋值给另外一个变量的时候,Python并没有拷贝这个对象,而只是拷贝这个对象的引用,并不会开辟新的内存空间。
a = [1, 2, [1, 2]]
b = [1, 2, [1, 2]]
c = a
# 判断以下结果
a == b 返回 True
a == c 返回 True
b == c 返回 True
a is b 返回 False
b is c 返回 False
a is c 返回 True
# 此时修改a的值,c的值也会跟着改变
a.append(3)
print(a)
print(b)
print(c)
输出:
a: [1, 2, [1, 2], 3]
b: [1, 2, [1, 2]]
c: [1, 2, [1, 2], 3]
解析:'相等' 和 '相同'是不一样的
- ==是比较运算符,用来比较对象值是否相同,若相等返回True, 否则返回False
- is是判断是否为同一个对象,即对象内存地址是否相同,若相同返回True,否则返回False
2. 浅拷贝
在Python中,浅拷贝就是拷贝了父对象,但是不会拷贝对象内部的子对象,其内容是原对象的引用。
浅拷贝要分两种情况进行讨论:
- 当浅拷贝是不可变对象(字符串,元组,数值类型)时和直接赋值情况一样,对象的id与浅拷贝对应的id相同
- 当浅拷贝是可变对象(列表,字典,集合)时:
- 复制的对象无复杂子对象,原来值的改变并不会有影响浅拷贝的值,同时浅拷贝复制的值改变也不会影响原来的值,原来对象的id与浅拷贝度对象id不同
- 复制的对象中有复杂子对象(例如列表中的一个子元素是一个列表),如果不改变其中复杂元素,浅拷贝的值改变不会影响原来的值,但是改变原来的值的复杂子对象的值会影响浅拷贝的值
3. 深拷贝
和浅拷贝对应,深拷贝拷贝对象的所有元素,包括多层嵌套的元素,深拷贝出来的对象是一个全新对象,不再和原来的对象有任何关联
import copy
a = [1, 2, 3, [4, 5], 6]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)
b.append(10)
c[3].append(11)
d[3].append(12)
print("a is:{}, b is:{}, c is:{}, d is:{}".format(a, b, c, d))
# 输出:
a is:[1, 2, 3, [4, 5, 11], 6, 10], b is:[1, 2, 3, [4, 5, 11], 6, 10], c is:[1, 2, 3, [4, 5, 11], 6], d is:[1, 2, 3, [4, 5, 12], 6]
解析:
如图所示:
- 由于b是a的赋值,所以b的改变会导致a也改变
- c是a的浅拷贝,c[3]是一个可变对象,所以改变c[3]值会影响a的值
- d是a的深拷贝,d[3]的改变并不影响a的值