Python 引用类型深度解析:从列表赋值到浅拷贝与深拷贝

张开发
2026/4/20 2:51:22 15 分钟阅读

分享文章

Python 引用类型深度解析:从列表赋值到浅拷贝与深拷贝
目录一、问题引入二、引用类型1、除列表外常见的可变引用类型2、引用类型的验证三、浅拷贝Shallow Copy与深拷贝Deep Copy1、浅拷贝2、深拷贝四、引用类型、浅拷贝、深拷贝对比表五、总结与最佳实践一、问题引入先看下面这段代码的输出结果original_list [1, 2, 3] new_list original_list new_list.remove(1) # 从 new_list 中移除元素 1 print(original_list)输出[2, 3]分析原本original_list是[1, 2, 3]。执行new_list original_list后new_list和original_list指向同一个列表对象。因此通过new_list.remove(1)修改列表时original_list也会同步改变。这就是引用类型的典型特征变量存储的是对象的引用内存地址赋值操作只是拷贝了引用而不是对象本身。二、引用类型在 Python 中一切皆对象变量本质上都是对对象的引用。但通常我们说的“引用类型”特指可变类型mutable types因为不可变类型如整数、字符串、元组在修改时会创建新对象不会影响原对象。1、除列表外常见的可变引用类型类型示例是否可变字典dictd {a: 1, b: 2}✅ 可变集合sets {1, 2, 3}✅ 可变自定义类的实例obj MyClass()✅ 可变除非使用不可变字段字节数组bytearrayba bytearray(bhello)✅ 可变数组模块array.arrayimport array; a array.array(i, [1,2,3])✅ 可变特别注意元组tuple虽然不可变但它包含的元素如果是可变对象则这些元素仍可被修改例如元组内嵌列表。但元组本身的引用不可变。函数、模块、文件对象等也是引用类型但通常不直接参与数据拷贝的讨论。2、引用类型的验证# 字典示例 d1 {x: 10} d2 d1 d2[x] 99 print(d1) # {x: 99} 被修改 # 集合示例 s1 {1, 2, 3} s2 s1 s2.add(4) print(s1) # {1, 2, 3, 4}三、浅拷贝Shallow Copy与深拷贝Deep Copy为了真正复制一个对象而不是共享引用我们需要使用拷贝技术。Python 提供了copy模块来实现浅拷贝和深拷贝。1、浅拷贝定义创建一个新对象但新对象内部的子对象仍然是原对象子对象的引用。适用场景对象内部没有嵌套的可变对象或者你希望共享内层子对象。方法copy.copy(obj)或类型自身的拷贝方法如列表的list.copy()字典的dict.copy()。浅拷贝示例import copy original [1, 2, [3, 4]] shallow copy.copy(original) # 或者 original.copy() # 修改外层元素不可变元素会新建 shallow[0] 99 print(original) # [1, 2, [3, 4]] 不受影响 # 修改内层列表可变对象 shallow[2][0] 999 print(original) # [1, 2, [999, 4]] 原对象被影响结论浅拷贝只复制最外层容器内层嵌套的可变对象仍然共享引用。2、深拷贝定义递归地复制对象及其所有子对象生成完全独立的副本。适用场景需要完全隔离原对象和新对象修改任意层级都不相互影响。方法copy.deepcopy(obj)。深拷贝示例import copy original [1, 2, [3, 4]] deep copy.deepcopy(original) deep[2][0] 888 print(original) # [1, 2, [3, 4]] 完全不受影响注意深拷贝可能开销较大且对于包含循环引用的对象需要特殊处理deepcopy能处理循环引用。四、引用类型、浅拷贝、深拷贝对比表操作是否创建新容器是否复制内层对象修改内层是否影响原对象直接赋值❌ 否❌ 否✅ 是浅拷贝copy.copy()✅ 是❌ 否仅复制引用✅ 是内层可变时深拷贝copy.deepcopy()✅ 是✅ 是递归❌ 否五、总结与最佳实践理解引用类型Python 中列表、字典、集合、类实例等都是可变引用类型。直接赋值不会创建副本而是让多个变量指向同一对象。需要独立副本时若对象没有嵌套可变结构如纯数字、字符串、元组的列表用浅拷贝即可。若对象包含嵌套列表/字典/自定义对象应使用深拷贝确保完全隔离。性能考量深拷贝比浅拷贝慢且占用更多内存只在必要时使用。不可变类型int、str、tuple修改时会创建新对象因此不存在“意外修改原对象”的问题但仍需注意不可变容器内嵌套可变对象的情况如元组内嵌列表。回到开头的代码只需改为浅拷贝或深拷贝即可避免相互影响original_list [1, 2, 3] new_list original_list.copy() # 浅拷贝这里没有嵌套效果等同于深拷贝 new_list.remove(1) print(original_list) # [1, 2, 3] 保持不变

更多文章