Python 深浅拷贝详解
在 Python 中,理解深拷贝(deep copy)和浅拷贝(shallow copy)对于处理复杂的数据结构,如列表、字典或自定义对象,是非常重要的。这两种拷贝方式决定了数据在内存中的复制方式,进而影响程序的运行结果。
详细解析了 Python 中的深浅拷贝概念。浅拷贝仅复制对象本身,内部子对象共享引用,适用于无嵌套可变对象或追求高性能的场景;深拷贝递归复制所有子对象,确保完全独立,适用于需要防止副作用或处理复杂嵌套结构的场景。文章提供了多种实现方式(如 copy 模块、切片、工厂函数)及代码示例,对比了两者在修改嵌套对象时的不同表现,并总结了实际应用场景如数据处理、配置管理和对象状态管理。

在 Python 中,理解深拷贝(deep copy)和浅拷贝(shallow copy)对于处理复杂的数据结构,如列表、字典或自定义对象,是非常重要的。这两种拷贝方式决定了数据在内存中的复制方式,进而影响程序的运行结果。
浅拷贝是一种复制操作,它创建一个新对象,并将原对象的内容复制到新对象中。对于原对象内部的子对象,浅拷贝不会递归地复制它们,而是直接引用这些子对象。因此,浅拷贝后的对象和原对象共享内部的子对象。
copy 模块的 copy() 函数import copy
original_list = [1, 2, [3, 4]]
shallow_copied_list = copy.copy(original_list)
original_list = [1, 2, [3, 4]]
shallow_copied_list = list(original_list) # 列表的工厂函数
original_list = [1, 2, [3, 4]]
shallow_copied_list = original_list[:] # 切片操作
copy() 方法original_dict = {'a': 1, 'b': [2, 3]}
shallow_copied_dict = original_dict.copy() # 字典的 copy() 方法
import copy
original_list = [1, 2, [3, 4]]
shallow_copied_list = copy.copy(original_list)
# 修改浅拷贝后的对象
shallow_copied_list[0] = 100
shallow_copied_list[2][0] = 300
print("Original List:", original_list)
print("Shallow Copied List:", shallow_copied_list)
输出:
Original List: [1, 2, [300, 4]]
Shallow Copied List: [100, 2, [300, 4]]
解释:
shallow_copied_list[0] 不会影响 original_list,因为这是对新对象本身的修改。shallow_copied_list[2][0] 会影响 original_list,因为内部的子列表是共享的。original_list = [1, 2, [3, 4]]
shallow_copied_list = original_list[:]
shallow_copied_list[0] = 100
shallow_copied_list[2][0] = 300
print("Original List:", original_list)
print("Shallow Copied List:", shallow_copied_list)
输出:
Original List: [1, 2, [300, 4]]
Shallow Copied List: [100, 2, [300, 4]]
original_dict = {'a': 1, 'b': [2, 3]}
shallow_copied_dict = original_dict.copy()
shallow_copied_dict['a'] = 100
shallow_copied_dict['b'][0] = 200
print("Original Dict:", original_dict)
print("Shallow Copied Dict:", shallow_copied_dict)
输出:
Original Dict: {'a': 1, 'b': [200, 3]}
Shallow Copied Dict: {'a': 100, 'b': [200, 3]}
解释:
shallow_copied_dict['a'] 不会影响 original_dict,因为这是对新对象本身的修改。shallow_copied_dict['b'][0] 会影响 original_dict,因为内部的列表是共享的。深拷贝(Deep Copy)是 Python 中一种递归复制对象的方式,它会创建一个新对象,并递归地复制原对象内部的所有子对象。这意味着深拷贝后的对象与原对象完全独立,修改其中一个不会影响另一个。深拷贝适用于需要完全独立副本的场景,尤其是当对象内部包含嵌套的可变对象时。
深拷贝是一种递归复制操作,它创建一个新对象,并递归地复制原对象内部的所有子对象。深拷贝后的对象与原对象完全独立,即使原对象包含嵌套的可变对象(如列表、字典等),修改其中一个对象也不会影响另一个。
在 Python 中,可以通过 copy 模块的 deepcopy() 函数实现深拷贝。
copy.deepcopy() 函数

输出:
Original List: [1, 2, [3, 4]]
Deep Copied List: [100, 2, [300, 4]]
解释:
deep_copied_list[0] 不会影响 original_list,因为这是对新对象本身的修改。deep_copied_list[2][0] 也不会影响 original_list,因为深拷贝递归复制了内部的子列表,两个列表是完全独立的。
输出:
Original Dict: {'name': 'Alice', 'details': {'age': 25, 'hobbies': ['reading', 'traveling']}}
Deep Copied Dict: {'name': 'Alice', 'details': {'age': 30, 'hobbies': ['reading', 'traveling', 'cooking']}}
解释:
deep_copied_dict 中的嵌套字典和列表不会影响 original_dict,因为深拷贝递归复制了所有子对象。
输出

解释:
copy.deepcopy() 函数已经处理了循环引用问题,但在自定义深拷贝逻辑时需要注意。Python 的 copy.deepcopy() 函数通过递归遍历对象的所有属性来实现深拷贝。它会维护一个备忘录(memo)来记录已经复制的对象,从而避免循环引用导致的无限递归。
在处理数据时,尤其是嵌套的数据结构(如列表嵌套列表、字典嵌套字典等),你可能需要在不影响原始数据的情况下对数据进行修改或分析。这时,深拷贝非常有用。
import copy
# 原始数据
original_data = {
'name': 'Alice',
'scores': [90, 85, 88],
'details': {'age': 25, 'city': 'New York'}
}
# 深拷贝数据
copied_data = copy.deepcopy(original_data)
# 修改拷贝后的数据
copied_data['scores'][0] = 95
copied_data['details']['city'] = 'San Francisco'
# 原始数据不受影响
print("Original Data:", original_data)
print("Copied Data:", copied_data)
应用场景:
在程序中,配置通常以字典或嵌套字典的形式存储。如果你需要基于某个默认配置生成多个独立的配置,深拷贝可以确保每个配置之间互不干扰。
import copy
# 默认配置
default_config = {
'debug': False,
'database': {
'host': 'localhost',
'port': 3306
}
}
# 创建多个独立配置
config_1 = copy.deepcopy(default_config)
config_2 = copy.deepcopy(default_config)
# 修改配置
config_1['database']['host'] = '192.168.1.1'
config_2['debug'] = True
print("Config 1:", config_1)
print("Config 2:", config_2)
应用场景:
在面向对象编程中,对象可能包含嵌套的对象或复杂的状态。如果你需要复制一个对象并确保新对象的状态独立于原对象,深拷贝是必要的。
import copy
class Player:
def __init__(self, name, level):
self.name = name
self.level = level
self.inventory = []
def add_item(self, item):
self.inventory.append(item)
# 创建玩家对象
player1 = Player("Alice", 10)
player1.add_item("Sword")
player1.add_item("Shield")
# 深拷贝玩家对象
player2 = copy.deepcopy(player1)
# 修改拷贝后的对象
player2.name = "Bob"
player2.add_item("Bow")
# 查看两个对象的状态
print(f"Player 1: {player1.name}, {player1.inventory}")
print(f"Player 2: {player2.name}, {player2.inventory}")
应用场景:
def process_data(data):
# 浅拷贝数据以避免修改原始数据
data_copy = data.copy()
data_copy.append("Processed")
return data_copy
original_data = [1, 2, 3]
result = process_data(original_data)
print("Original Data:", original_data)
print("Result:", result)
建议根据具体的需求和数据结构选择使用深拷贝还是浅拷贝。如果你不确定,深拷贝通常是更安全的选择,尽管它可能会带来一些性能开销。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML 转 Markdown 互为补充。 在线工具,Markdown 转 HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML 转 Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online