在日常编程中我们经常需要将一个对象“复制”一份用于备份、修改、撤销操作或独立的数据加工。然而Python 中的赋值语句b a并不会复制对象而是创建一个新的引用——两个变量指向内存中的同一对象修改一个会影响另一个。这种隐式共享在配置模板克隆、游戏单位生成、文本编辑器的撤销栈、数据分析的中间结果暂存等场景中会引发难以追踪的副作用。copy模块提供了两种复制机制浅拷贝copy.copy和深拷贝copy.deepcopy。浅拷贝创建一个新对象但内部元素是原对象元素的引用深拷贝则递归复制所有层级生成完全独立的对象。在生活中这类似于你做手工艺品时浅拷贝是复印一张图纸图纸上的零件列表还是原来的深拷贝则是把图纸上的每个零件都做出一份副本修改副本不会影响原件。实际应用包括备份用户输入的复杂表单数据以便“重置”、多线程任务中独立处理同一份原始数据、游戏开发中克隆敌人生成新个体等。一、安装库copy是 Python 标准库无需安装。直接导入pythonimport copy通常只需要copy.copy()和copy.deepcopy()两个函数。二、基本用法下面通过 4 个小步骤掌握copy的核心使用。1. 理解赋值与拷贝的区别pythonimport copy original [1, 2, [3, 4]] assigned original # 赋值共享同一对象 shallow copy.copy(original) # 浅拷贝 deep copy.deepcopy(original)# 深拷贝 original[0] 99 original[2][0] 88 print(assigned) # [99, 2, [88, 4]] → 随原对象改变 print(shallow) # [1, 2, [88, 4]] → 外层独立内层可变对象共享 print(deep) # [1, 2, [3, 4]] → 完全独立2. 浅拷贝copy.copy()浅拷贝适用场景对象顶层需要独立但内部元素为不可变类型如整数、字符串、元组或你希望共享子对象时。pythonsimple [1, 2, 3] shallow_simple copy.copy(simple) simple.append(4) print(shallow_simple) # [1, 2, 3] → 不影响因为外层是独立列表3. 深拷贝copy.deepcopy()深拷贝递归复制所有层级完全独立。注意深拷贝可能导致无限递归循环引用但deepcopy内置处理机制。pythonoriginal [{name: Alice}, {name: Bob}] deep_copy copy.deepcopy(original) original[0][name] Charlie print(deep_copy[0][name]) # Alice → 不受影响4. 自定义对象的复制自定义类可以通过实现__copy__()和__deepcopy__()方法来自定义复制行为。pythonclass Person: def __init__(self, name, friendsNone): self.name name self.friends friends or [] def __copy__(self): # 浅拷贝新建一个人共享朋友列表 new type(self)(self.name, self.friends) return new def __deepcopy__(self, memo): # 深拷贝递归复制朋友列表 new type(self)(self.name, copy.deepcopy(self.friends, memo)) return new三、高级用法使用copyreg注册自定义拷贝函数对于某些不可复制或需要特殊处理的对象如文件句柄、数据库连接可以通过copyreg模块定制deepcopy的行为。pythonimport copyreg class Connection: def __init__(self, host): self.host host self._open True def close(self): self._open False def pickle_conn(conn): # 返回 (构造函数, 参数元组) return (Connection, (conn.host,)) copyreg.pickle(Connection, pickle_conn) # 注册 conn Connection(localhost) conn_copy copy.deepcopy(conn) # 现在可以深拷贝会调用pickle_conn创建新实例处理循环引用与自定义memodeepcopy使用memo字典记录已复制的对象避免无限递归。你也可以手动传递memo实现更精细的控制。pythona [1, 2] b [a, a] # b 中两个元素引用同一列表 a deep_b copy.deepcopy(b) # deep_b[0] is deep_b[1] → True保持引用结构 # 高级手动控制 memo memo {} c1 copy.deepcopy(a, memo) c2 copy.deepcopy(a, memo) # 从 memo 中复用c2 与 c1 是同一对象四、实际应用场景场景1文本编辑器的“撤销”功能每次用户输入前将当前文档状态深拷贝存入历史栈。注意优化可以结合浅拷贝 不可变数据但为清晰演示使用深拷贝。pythonimport copy class TextEditor: def __init__(self): self.content [] self.history [] # 存储历史状态的深拷贝 def type_line(self, line): # 保存当前状态到历史深拷贝 self.history.append(copy.deepcopy(self.content)) self.content.append(line) def undo(self): if self.history: self.content self.history.pop() else: print(Nothing to undo) editor TextEditor() editor.type_line(Hello) editor.type_line(World) print(editor.content) # [Hello, World] editor.undo() print(editor.content) # [Hello]场景2游戏中的敌人生成器克隆原型使用原型模式通过深拷贝复制一个基础敌人对象再个性化修改避免重复创建相同属性。pythonimport copy class Enemy: def __init__(self, name, hp, skills): self.name name self.hp hp self.skills skills # 列表每个技能是字典 def clone(self): return copy.deepcopy(self) # 原型 base_goblin Enemy(Goblin, 30, [{name: stab, damage: 5}]) # 生成多个变体 goblin_a base_goblin.clone() goblin_a.name Goblin Archer goblin_a.skills.append({name: shoot, damage: 4}) goblin_b base_goblin.clone() goblin_b.hp 40 print(goblin_b.skills) # 只有 [{name: stab, damage: 5}]不影响原型的技能场景3配置模板的个性化分支运维脚本中有一份基础服务器配置字典为多个环境开发、测试、生产生成独立配置避免互相污染。pythonimport copy base_config { app_name: MyApp, database: { host: localhost, port: 5432, credentials: {user: admin, password: secret} } } dev copy.deepcopy(base_config) dev[database][host] dev.db.com dev[database][credentials][password] devpass test copy.deepcopy(base_config) test[database][port] 5433 # 生产保持原样但因为是深拷贝互不干扰 print(base_config[database][host]) # localhost print(dev[database][host]) # dev.db.com五、结尾互动总结一下copy模块通过浅拷贝和深拷贝完美解决了对象复制中的“共享引用”问题。浅拷贝适合性能敏感且子对象不会独立修改的场景如只读共享数据深拷贝则适用于需要完全隔离的场合如撤销系统、原型克隆。使用时要注意深拷贝可能耗时且内存占用大对于包含文件、网络连接等资源型对象需要自定义__deepcopy__或使用copyreg避免错误。你是否曾在项目中因为忘记深拷贝而踩过坑比如一个列表字典被多处意外修改导致的诡异 bug或者你开发过依赖对象复制的有趣工具欢迎在评论区分享你的故事或提问一起探讨 Python 复制的最佳实践。