Python 中的浅拷贝 vs 深拷贝:面向面试的解释

发布: (2025年12月23日 GMT+8 21:41)
5 min read
原文: Dev.to

Source: Dev.to

Introduction

最常见的 Python 面试题之一听起来貌似很简单:

“Python 中浅拷贝和深拷贝有什么区别?”

面试官通过这个问题来考察:

  • 对可变对象与不可变对象的理解
  • 对对象引用的把握
  • 推理副作用和 bug 的能力
  • 对真实 Python 行为的认识(而不仅仅是定义)

这在后端、数据和机器学习岗位尤为重要。

浅拷贝

浅拷贝 会创建一个新的容器对象,但 不会 递归地复制其中的对象。外层对象被复制,而内部对象仍然是共享的引用。

import copy

original = [[1, 2], [3, 4]]
shallow = copy.copy(original)

shallow[0].append(99)

print(original)  # [[1, 2, 99], [3, 4]]
print(shallow)   # [[1, 2, 99], [3, 4]]
  • originalshallow 是不同的列表,但它们内部的列表指向同一块内存。

深拷贝

深拷贝 会创建一个新的容器 并且 递归复制所有嵌套对象,从而没有共享的引用。复制得到的结构是完全独立的。

import copy

original = [[1, 2], [3, 4]]
deep = copy.deepcopy(original)

deep[0].append(99)

print(original)  # [[1, 2], [3, 4]]
print(deep)      # [[1, 2, 99], [3, 4]]
  • deep 的更改不会影响 original

类比

  • 浅拷贝 → 复制盒子本身,而不是里面的项目。
  • 深拷贝 → 复制盒子 以及 里面的所有内容。

这种类比有助于在面试中快速传达概念。

Python 中常见的复制方式

OperationType of CopyNote
list.copy()浅拷贝
list[:]浅拷贝切片始终是浅拷贝
dict.copy()浅拷贝
copy.copy(obj)浅拷贝
copy.deepcopy(obj)深拷贝更耗时且占用更多内存
b = a无复制简单赋值共享同一对象

重要陷阱

  • 误解: “浅拷贝一次就复制了所有内容。”

    • 实际情况: 嵌套的可变对象仍然是共享的。
  • 深拷贝的代价:

    • 执行速度更慢
    • 内存占用更高
    • 可能破坏对对象身份的假设
  • 不可变对象(例如 intstrtuple)不会导致共享状态问题。

何时避免深拷贝

  • 对性能有要求的大型、深层嵌套结构
  • 持有外部资源的对象(文件、数据库连接)
  • 在可以接受受控共享数据变更的情形下

自定义复制行为

高级面试候选人可能会提到,自定义类可以通过实现以下方法来控制复制:

def __copy__(self):
    # return a shallow copy of the instance
    ...

def __deepcopy__(self, memo):
    # return a deep copy of the instance
    ...

这表明了高级水平的理解,因为许多框架依赖这些钩子。

Structured Answer to the Interview Question

浅拷贝创建一个新的容器,但对嵌套对象共享引用,而深拷贝则递归地复制所有对象。浅拷贝速度更快且节省内存,但在可变的嵌套数据上可能导致副作用。深拷贝避免共享状态,但代价更高。Python 提供 copy.copy() 用于浅拷贝,copy.deepcopy() 用于深拷贝。

实际复制相关的错误

  • 共享引用: 在一个副本中修改嵌套对象会意外影响另一个副本。
  • 假设独立性: 将浅拷贝视为完全独立会导致细微错误。

了解这些错误产生的原因,可帮助你在面试场景和生产代码中都自信应对。

Back to Blog

相关文章

阅读更多 »