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() 函数实现深拷贝。
import copy
deep_copied_list = copy.deepcopy(original_list)

import copy
original_list = [1, 2, [3, 4]]
deep_copied_list = copy.deepcopy(original_list)
# 修改深拷贝后的对象
deep_copied_list[0] = 100
deep_copied_list[2][0] = 300
print("Original List:", original_list)
print("Deep Copied List:", deep_copied_list)
输出:
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,因为深拷贝递归复制了内部的子列表,两个列表是完全独立的。
import copy
original_dict = {'name': 'Alice', 'details': {'age': 25, 'hobbies': ['reading', 'traveling']}}
deep_copied_dict = copy.deepcopy(original_dict)
# 修改深拷贝后的字典
deep_copied_dict['details']['age'] = 30
deep_copied_dict['details']['hobbies'].append('cooking')
print("Original Dict:", original_dict)
print("Deep Copied Dict:", deep_copied_dict)
输出:
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,因为深拷贝递归复制了所有子对象。
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}")
解释:
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)
应用场景:
在面向对象编程中,对象可能包含嵌套的对象或复杂的状态。如果你需要复制一个对象并确保新对象的状态独立于原对象,深拷贝是必要的。
应用场景:
在函数中传递复杂对象时,深拷贝可以避免意外修改原对象。
def process_data(data):
data_copy = copy.deepcopy(data)
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
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
解析常见 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