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]

解析:'相等' 和 '相同'是不一样的

  1. ==是比较运算符,用来比较对象值是否相同,若相等返回True, 否则返回False
  2. is是判断是否为同一个对象,即对象内存地址是否相同,若相同返回True,否则返回False

2. 浅拷贝

在Python中,浅拷贝就是拷贝了父对象,但是不会拷贝对象内部的子对象,其内容是原对象的引用。
浅拷贝要分两种情况进行讨论:

  • 当浅拷贝是不可变对象(字符串,元组,数值类型)时和直接赋值情况一样,对象的id与浅拷贝对应的id相同
  • 当浅拷贝是可变对象(列表,字典,集合)时:
    1. 复制的对象无复杂子对象,原来值的改变并不会有影响浅拷贝的值,同时浅拷贝复制的值改变也不会影响原来的值,原来对象的id与浅拷贝度对象id不同
    2. 复制的对象中有复杂子对象(例如列表中的一个子元素是一个列表),如果不改变其中复杂元素,浅拷贝的值改变不会影响原来的值,但是改变原来的值的复杂子对象的值会影响浅拷贝的值

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]

解析:
如图所示:

  1. 由于b是a的赋值,所以b的改变会导致a也改变
  2. c是a的浅拷贝,c[3]是一个可变对象,所以改变c[3]值会影响a的值
  3. d是a的深拷贝,d[3]的改变并不影响a的值
    image
posted @ 2022-03-13 15:34  KB、渣科  阅读(96)  评论(0编辑  收藏  举报