零基础小白Python入门必看:通俗易懂,搞定深浅拷贝

Python中的深浅拷贝在讲深浅拷贝之前 , 想先讲一下 is 和==的区别 。
在进行对象是否相等比较的时候我们可以用is 和 ==

  • is:比较两个对象的引用是否相同 , 即 它们的id 是否一样
  • == : 比较两个对象的值是否相同 。
id(), 是Python的一个内置函数 , 返回对象的唯一标识 , 用于获取对象的内存地址 。
如下
a = 1b = 1print(id(a)) # 2057422768print(id(b)) # 2057422768print(a is b) # True复制代码首先 , 会为整数1分配一个内存空间 。变量a 和 b 都指向了这个内存空间(内存地址相等) , 所以他们的id相等 。
即 a is b 为 True
零基础小白Python入门必看:通俗易懂,搞定深浅拷贝文章插图
如果大家在学习中遇到困难 , 想找一个python学习交流环境 , 可以加入我们的python裙 , 关注小编 , 并私信“01”即可进裙 , 领取python学习资料 , 会节约很多时间 , 减少很多遇到的难题 。
但是 , 真的所有整数数字都这样吗? 答案是:不是! 只有在 -25 ~ 256范围中的整数才不会重新分配内存空间 。
如下所示:
因为257 超出了范围 , 所以id不相同 , 所以a is b返回的值为False 。
>>> a = 257>>> b = 257>>> print(id(a))20004752>>> print(id(b))20001312>>> print(a is b)False>>> print(a == b)True复制代码这样做是考虑到性能 , Python对-5 到 256 的整数维护了一个数组 , 相当于一个缓存 ,当数值在这个范围内 , 直接就从数组中返回相对应的引用地址了 。 如果不在这个范围内 , 会重新开辟一个新的内存空间 。
is 和 == 哪个效率高?相比之下 , is比较的效率更高 , 因为它只需要判断两个对象的id是否相同即可 。
而== 则需要重载eq 这个函数 , 遍历变量中的所有元素内容 , 逐次比较是否相同 。 因此效率较低
浅拷贝 深拷贝简单的了解了is ,== ,下面我们一起来看看Python中的深浅拷贝 。
先说结论吧:
  • 浅拷贝:拷贝的是对象的引用 , 如果原对象改变 , 相应的拷贝对象也会发生改变
  • 深拷贝:拷贝对象中的每个元素 , 拷贝对象和原有对象不在有关系 , 两个是独立的对象

零基础小白Python入门必看:通俗易懂,搞定深浅拷贝文章插图
浅拷贝a = [1, 2, 3]b = list(a)# 可以通过list 对列表进行浅拷贝c = a.copy() # 也可以通过copy函数进行拷贝# 浅拷贝后 , a/b/c的id 各不相同 , 说明指向了不同的内存地址-- 即 生成了新的对象print(id(a)) # 16301992print(b, "id:", id(b)) # id:16562024print(c, "id:", id(c)) # id:16561960print(a == b) # True值相同 返回Trueprint(a is b) # Falseid不同所以 is比较返回False# 给列表a 添加元素4a.append(4)print(a) # [1, 2, 3, 4]print(b, c) # [1, 2, 3] [1, 2, 3]b和c 不受影响复制代码以上可以看出 , 浅拷贝会分配一个新的内存空间 , 创建一个新的对象 。 但是如果被拷贝对象中有可变对象会怎么样呢? 看下面的代码
a = [1, 2, [3, 4]]b = a.copy()print(id(a)) # 23967528print(id(b)) # 21738984# 改变a中的可变对象a[-1].append(5)print(a)# 在给a新增元素6a.append(6)# [1, 2, [3, 4, 5], 6]print(a)# [1, 2, [3, 4, 5]]print(b)复制代码可以看出 , 在列表a中新增的元素6 , 并没有影响b 。 但是在a的嵌套列表中新增的元素5 , 却影响了元素b 。
原因在于:对于a和b都指向了同一个列表[3, 4] 。所以当a中在列表新增元素5的时候 , 改变了那个列表的值 , b也指向了那个列表 , 所以也会发生改变 。


推荐阅读