刚学Python的同学大概率都踩过这个坑:
明明改的是复制出来的新列表,原列表居然也跟着变了?
搞不清深浅拷贝,写代码时很容易留下隐蔽的bug,排查起来还特别头疼。
🔍 一、先搞懂最基础的底层逻辑
Python里所有变量存的都是对象的引用地址,不是对象本身。
我们平时写的 a = [1,2,3],其实a只是个指向列表对象的"门牌号"。
直接赋值 b = a 本质是多贴了一个门牌号,指向的还是同一个房子。
我们先看个最直观的例子:
a = [1, 2, [3, 4]] b = a b[0] = 99 print(a) # 输出:[99, 2, [3, 4]] # 改b会影响a,因为两者指向同一个对象
💡 二、浅拷贝:只拷贝第一层
浅拷贝的核心逻辑:只复制容器本身,内部元素还是引用原来的对象。
对于只有一层元素的不可变对象,浅拷贝完全够用;但如果有嵌套的可变元素,坑就来了。
常见的浅拷贝实现方式
- 列表切片:
new_list = old_list[:] - 工厂方法:
new_list = list(old_list) - copy模块的copy方法:
new_obj = copy.copy(old_obj)
我们直接上代码看效果:
import copy a = [1, 2, [3, 4]] b = copy.copy(a) # 浅拷贝 b[0] = 99 # 修改第一层元素 b[2][0] = 66 # 修改嵌套的内层元素 print(a) # 输出:[1, 2, [66, 4]] print(b) # 输出:[99, 2, [66, 4]] # 注意:内层元素修改影响了原对象,第一层修改不影响
⚡ 三、深拷贝:完全独立的副本
深拷贝就简单粗暴多了:递归复制所有层级的对象,新对象和原对象完全独立。
不管你有多少层嵌套,修改新对象的任何元素,都不会影响原对象。
唯一需要注意的是,如果对象里有循环引用,深拷贝会自动处理不会死循环,只是性能会稍差一点。
同样上代码对比:
import copy a = [1, 2, [3, 4]] b = copy.deepcopy(a) # 深拷贝 b[0] = 99 b[2][0] = 66 print(a) # 输出:[1, 2, [3, 4]] print(b) # 输出:[99, 2, [66, 4]] # 完全互不影响
📌 怎么选?一张表给你理清楚
✅ 数据只有一层、都是不可变类型(字符串、数字、元组):用浅拷贝,性能更好 ✅ 有嵌套的可变类型(列表、字典),需要完全独立的副本:用深拷贝 ❌ 不要用直接赋值来复制对象,除非你明确知道自己在做什么
以后再遇到改一个对象另一个跟着变的bug,先想想是不是拷贝用错了~
觉得有用的话可以点个在看,分享给身边刚学Python的朋友哦😉
欢迎一块交流学习,有需要的可以点个关注哈。