字典插入本身不慢,慢在错误使用:循环频繁重建、键类型混用、误调.keys()等触发拷贝、Numba修饰反降速、或当成缓冲区/数据库滥用。

字典本身不是瓶颈,性能下降几乎都来自你“怎么用”字典——尤其是混用 Python 原生字典和 Numba、频繁重建、键类型混乱或误判适用场景时。
为什么 dict 插入变慢?先看真实瓶颈在哪
Python 的 dict 是 C 实现的哈希表,单次 __setitem__ 平均 O(1),插入 100 万条通常不到 0.1 秒。所谓“大批量变慢”,90% 情况下是以下原因叠加:
- 你在循环里反复创建新
dict(比如每次迭代d = {}),触发大量内存分配 + 哈希表初始化开销 - 键类型不一致(
str、int、tuple混用),导致 Numba 无法推断类型,回退到解释执行甚至报错 - 把
dict当缓冲区,在高频写入中又频繁调用.keys()、.values()或list(d.items()),触发全量拷贝 - 误用
dict存储可预测结构数据(如固定字段日志),却没考虑__slots__类或namedtuple更省内存
@nb.njit 修饰含字典的函数反而更慢
Numba 对 dict 支持有限,且默认不加速原生 dict 操作。一旦你加了 @nb.njit,反而会触发:
- JIT 编译时对字典键/值做复杂类型推断,首次调用延迟明显
- 运行时为兼容 Python 字典语义,插入操作被降级为带锁的通用路径,比纯 Python 还慢
- 若键是字符串,Numba 会尝试转成
unicode内部表示,引入额外编码开销
验证方法:去掉 @nb.njit,用 timeit 对比,通常原生 Python 快 2–5 倍。
立即学习“Python免费学习笔记(深入)”;
大批量构建字典的正确姿势
别在循环里逐个 d[k] = v,尤其当键可预知时:
- 用字典推导式:
{k: expensive_func(k) for k in keys},比循环快 30–50% - 键值已存在列表?直接
dict(zip(keys, values)),避免循环解释器开销 - 需要条件过滤?用生成器表达式:
dict((k, v) for k, v in items if k not in blacklist) - 超大规模(百万级)且键为整数?考虑
array.array('i', [...])或numpy.ndarray替代稀疏字典
真正该警惕的“慢字典”信号
这些现象比“插入慢”更值得立刻检查:
- 内存占用暴涨(用
asizeof.asizeof(your_dict)测),可能是键太长或重复字符串未 intern -
dict作为类属性被意外共享(如class A: cache = {}),引发并发写冲突或静默污染 - 在多线程中无锁修改同一
dict,触发 GIL 频繁切换,实际是并发问题不是字典问题 - 用
json.dumps(dict_obj)频繁序列化大字典,瓶颈其实在 JSON 编码器,不是插入本身
字典插入本身极少是真瓶颈;慢的永远是周边动作——创建、复制、序列化、跨层传递或错误地把它当数据库用。



















