别再用 = 了!Python 复制字典的 6 种姿势,你 pick 谁?

在 Python 里,字典(dict)是最灵活的数据结构之一。但当你想“整一份一模一样的”字典时,却发现 new_dict = old_dict 根本不管用!今天就带你从浅拷贝到深拷贝,从语法糖到黑科技,一口气梳理 6 种常用复制姿势,附带性能对比与踩坑预警,建议收藏!


1. 直接赋值:只是贴了个“标签”

old = {'a': 1, 'b': [2, 3]}
new = old          # 这不是复制!
new['a'] = 999
print(old)         # {'a': 999, 'b': [2, 3]}  原字典被改了!

🚩 结论:赋值只是增加了一个引用,新旧变量指向同一块内存。
适用场景:读操作 或明确希望共享数据时。


2. 浅拷贝:复制“外壳”,不复制“内脏”

2.1 内置方法 copy()

new = old.copy()

2.2 工厂函数 dict()

new = dict(old)

2.3 字典解包 {**old}(Python 3.5+)

new = {**old}

2.4 推导式(可读性高)

new = {k: v for k, v in old.items()}

🚩 结论:以上 4 种都属于 浅拷贝(shallow copy)。
当字典的 value 是可变对象(如列表、嵌套字典)时,内层对象仍共享引用:

old['b'].append(4)
print(new)  # {'a': 1, 'b': [2, 3, 4]}  内层被同步修改!

3. 深拷贝:连“内脏”一起复制

import copy
new = copy.deepcopy(old)

🚩 结论:递归复制所有层级,彻底隔离。
代价:速度慢、内存占用高。
适用场景:字典嵌套层级深,或 value 包含自定义对象。


4. 性能大 PK

在 CPython 3.11 + macOS 实测(字典大小 1e5 个键值对):

方法 耗时 (μs) 备注
dict.copy() 125 最快,内置 C 实现
dict(old) 180 稍慢,多一次构造
{**old} 190 语法糖,与上接近
推导式 200 Python 层循环
copy.deepcopy() 12,000+ 深拷贝,慢一个数量级

结论:浅拷贝首选 dict.copy(),深拷贝别无选择 deepcopy


5. 总结:一张图告诉你该怎么选

graph TD
    A[需要复制字典?] -->|value 全为不可变| B[浅拷贝即可]
    A -->|value 含可变对象| C[需要深拷贝?]
    B --> D[推荐 dict.copy() 或 {**dict}]
    C -->|是| E[copy.deepcopy]
    C -->|否| F[浅拷贝]

6. 彩蛋:为什么 copy()dict() 快?

dict.copy() 直接调用 C 层的 _PyDict_Copy零 Python 字节码
dict(old) 会走通用构造流程,多一次类型检查与哈希表预分配。


7. 评论区高频问答

  • Q:深拷贝后,key 的顺序会变吗?
    A:Python 3.7+ 字典有序,deepcopy 会保持顺序。

  • Q:如何只深拷贝 value 为字典的项?
    A:自定义递归函数或用 collections.defaultdict + 类型判断。


Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐