python中的深浅拷贝

浅拷贝 (Shallow Copy)

浅拷贝创建一个新对象,但只复制原对象的引用,而不复制引用的对象本身。

实现方式

import copy

# 原始列表
original_list = [1, 2, 3]

# 方法1: 使用copy模块的copy()函数
shallow_copied1 = copy.copy(original_list)

# 方法2: 对于列表,可以使用切片操作
shallow_copied2 = original_list[:]

# 方法3: 使用list()构造函数
shallow_copied3 = list(original_list)

# 方法4: 使用对象的copy()方法(如果可用)
shallow_copied4 = original_list.copy()

浅拷贝的特点

import copy

# 示例1: 简单列表(无嵌套)
original = [1, 2, 3]
copied = copy.copy(original)

print("修改前:")
print(f"original: {original}")  # [1, 2, 3]
print(f"copied: {copied}")      # [1, 2, 3]

# 修改原始列表的第一层元素
original[0] = 100

print("\n修改后:")
print(f"original: {original}")  # [100, 2, 3]
print(f"copied: {copied}")      # [1, 2, 3] - 不受影响

修改前:
original: [1, 2, 3]
copied: [1, 2, 3]

修改后:
original: [100, 2, 3]
copied: [1, 2, 3]

# 示例2: 嵌套列表(展示浅拷贝的局限性)
import copy

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

print("修改前:")
print(f"original: {original}")  # [1, 2, [3, 4]]
print(f"copied: {copied}")      # [1, 2, [3, 4]]

print(f"\n嵌套列表的ID:")
print(f"original[2] id: {id(original[2])}")  # 某个内存地址
print(f"copied[2] id: {id(copied[2])}")      # 相同的地址!

# 修改原始数据的嵌套部分
original[2][0] = 300

print("\n修改嵌套元素后:")
print(f"original: {original}")  # [1, 2, [300, 4]]
print(f"copied: {copied}")      # [1, 2, [300, 4]] - 也被修改了!

修改前:
original: [1, 2, [3, 4]]
deep_copied: [1, 2, [3, 4]]

嵌套列表的ID:
original[2] id: 1994301925120
deep_copied[2] id: 1994301925376

修改嵌套元素后:
original: [1, 2, [300, 4]]
deep_copied: [1, 2, [3, 4]]

深拷贝 (Deep Copy)

深拷贝创建一个新对象,并递归地复制原对象及其所有子对象。

实现方式

import copy

original_list = [1, 2, [3, 4]]
deep_copied = copy.deepcopy(original_list)

深拷贝的特点

import copy

# 示例
original = [1, 2, [3, 4]]
deep_copied = copy.deepcopy(original)

print("修改前:")
print(f"original: {original}")     # [1, 2, [3, 4]]
print(f"deep_copied: {deep_copied}")  # [1, 2, [3, 4]]

print(f"\n嵌套列表的ID:")
print(f"original[2] id: {id(original[2])}")  # 某个内存地址
print(f"deep_copied[2] id: {id(deep_copied[2])}")  # 不同的地址!

# 修改原始数据的嵌套部分
original[2][0] = 300

print("\n修改嵌套元素后:")
print(f"original: {original}")     # [1, 2, [300, 4]]
print(f"deep_copied: {deep_copied}")  # [1, 2, [3, 4]] - 完全不受影响

修改前:
original: [1, 2, [3, 4]]
deep_copied: [1, 2, [3, 4]]

嵌套列表的ID:
original[2] id: 1994301936192
deep_copied[2] id: 1994301932352

修改嵌套元素后:
original: [1, 2, [300, 4]]
deep_copied: [1, 2, [3, 4]]

综合对比示例

import copy

# 创建包含多层嵌套结构的原始数据
original = [1, 2, ['a', 'b', {'x': 1, 'y': 2}]]

# 浅拷贝
shallow_copy = copy.copy(original)

# 深拷贝
deep_copy = copy.deepcopy(original)

print("=== 内存地址对比 ===")
print(f"原始列表ID: {id(original)}")
print(f"浅拷贝列表ID: {id(shallow_copy)}")
print(f"深拷贝列表ID: {id(deep_copy)}")

print(f"\n原始嵌套列表ID: {id(original[2])}")
print(f"浅拷贝嵌套列表ID: {id(shallow_copy[2])}")  # 与原始相同
print(f"深拷贝嵌套列表ID: {id(deep_copy[2])}")     # 新的ID

print(f"\n原始嵌套字典ID: {id(original[2][2])}")
print(f"浅拷贝嵌套字典ID: {id(shallow_copy[2][2])}")  # 与原始相同
print(f"深拷贝嵌套字典ID: {id(deep_copy[2][2])}")     # 新的ID

# 修改测试
print("\n=== 修改测试 ===")
original[2][0] = 'MODIFIED'
original[2][2]['x'] = 999

print(f"原始: {original}")        # [1, 2, ['MODIFIED', 'b', {'x': 999, 'y': 2}]]
print(f"浅拷贝: {shallow_copy}")  # [1, 2, ['MODIFIED', 'b', {'x': 999, 'y': 2}]] - 受影响
print(f"深拷贝: {deep_copy}")     # [1, 2, ['a', 'b', {'x': 1, 'y': 2}]] - 不受影响

=== 内存地址对比 ===
原始列表ID: 1994285283008
浅拷贝列表ID: 1994285284800
深拷贝列表ID: 1994301925120

原始嵌套列表ID: 1994285283712
浅拷贝嵌套列表ID: 1994285283712
深拷贝嵌套列表ID: 1994301923968

原始嵌套字典ID: 1994285271808
浅拷贝嵌套字典ID: 1994285271808
深拷贝嵌套字典ID: 1994285276224

=== 修改测试 ===
原始: [1, 2, ['MODIFIED', 'b', {'x': 999, 'y': 2}]]
浅拷贝: [1, 2, ['MODIFIED', 'b', {'x': 999, 'y': 2}]]
深拷贝: [1, 2, ['a', 'b', {'x': 1, 'y': 2}]]

字典的拷贝示例

import copy

# 字典的拷贝
original_dict = {
    'name': 'Alice',
    'scores': [85, 92, 78],
    'info': {'age': 25, 'city': 'Beijing'}
}

# 浅拷贝
shallow_dict = copy.copy(original_dict)

# 深拷贝
deep_dict = copy.deepcopy(original_dict)

# 修改测试
original_dict['scores'][0] = 100
original_dict['info']['age'] = 26

print("原始字典:", original_dict)
# {'name': 'Alice', 'scores': [100, 92, 78], 'info': {'age': 26, 'city': 'Beijing'}}

print("浅拷贝字典:", shallow_dict)
# {'name': 'Alice', 'scores': [100, 92, 78], 'info': {'age': 26, 'city': 'Beijing'}}

print("深拷贝字典:", deep_dict)
# {'name': 'Alice', 'scores': [85, 92, 78], 'info': {'age': 25, 'city': 'Beijing'}}

原始字典: {'name': 'Alice', 'scores': [100, 92, 78], 'info': {'age': 26, 'city': 'Beijing'}}
浅拷贝字典: {'name': 'Alice', 'scores': [100, 92, 78], 'info': {'age': 26, 'city': 'Beijing'}}
深拷贝字典: {'name': 'Alice', 'scores': [85, 92, 78], 'info': {'age': 25, 'city': 'Beijing'}}

实际应用场景

浅拷贝适用场景

# 场景1: 数据结构简单,没有嵌套的可变对象
config = {'debug': True, 'port': 8080}
backup_config = config.copy()  # 或 copy.copy(config)

# 场景2: 需要共享某些数据
shared_data = {'last_updated': '2024-01-01'}
cache1 = {'data': shared_data}
cache2 = cache1.copy()

# cache1和cache2共享同一个last_updated字典

深拷贝适用场景

# 场景1: 需要完全独立的配置模板
template = {
    'database': {
        'host': 'localhost',
        'port': 5432,
        'credentials': {'user': 'admin', 'password': 'secret'}
    },
    'settings': {'timeout': 30, 'retries': [1, 2, 3]}
}

# 为不同环境创建独立配置
development_config = copy.deepcopy(template)
production_config = copy.deepcopy(template)

# 修改开发配置不会影响生产配置
development_config['database']['host'] = 'dev-server'
development_config['settings']['retries'][0] = 0

性能考虑

import copy
import time

# 创建大型嵌套数据结构
def create_large_data():
    return [[[i*j*k for k in range(100)] for j in range(100)] for i in range(10)]

large_data = create_large_data()

# 测试浅拷贝性能
start = time.time()
shallow_copy = copy.copy(large_data)
shallow_time = time.time() - start

# 测试深拷贝性能
start = time.time()
deep_copy = copy.deepcopy(large_data)
deep_time = time.time() - start

print(f"浅拷贝时间: {shallow_time:.6f}秒")
print(f"深拷贝时间: {deep_time:.6f}秒")
print(f"深拷贝比浅拷贝慢 {deep_time/shallow_time:.2f} 倍")

总结表格

特性 浅拷贝 深拷贝
复制层级 只复制第一层 递归复制所有层级
嵌套对象 共享引用 创建新对象
内存使用 较少 较多
性能 较快 较慢
修改影响 嵌套对象修改会影响拷贝 完全独立,互不影响
适用场景 简单结构或需要共享嵌套对象时 需要完全独立副本时

关键要点

  1. 浅拷贝:创建新容器,但填充的是对原对象内容的引用
  2. 深拷贝:创建新容器,并递归地添加原对象内容的副本
  3. 对于不可变对象(数字、字符串、元组等),深浅拷贝没有区别
  4. 当不确定时,使用深拷贝可以避免意外的副作用
  5. 考虑性能,对于大型数据结构,深拷贝可能较慢
posted @ 2025-11-13 14:48  人间的树  阅读(0)  评论(0)    收藏  举报