字典是 Python 里另一个”灵魂容器”。它把”键 → 值”的映射用最直观的方式呈现出来,几乎所有 Python 项目都离不开它——JSON、配置、缓存、计数器、图的邻接表,能用字典表达的场景多到数不清。这一篇要把字典讲透:创建、增删改查、遍历、常用方法、Python 3.7+ 顺序保证、以及新手最容易踩的键类型和默认值陷阱。
一、什么是字典
字典(dict)是一个 可变 的、键值对(key-value) 集合。用大括号加冒号创建:
1 | empty = {} |
关键约束:
- key 必须是可哈希的:字符串、数字、元组(内部也是不可变)都行;list/dict/set 不行;
- key 唯一:同名 key 后写的覆盖先写的;
- value 什么都行:任意 Python 对象。
二、创建字典的多种方式
1 | # 字面量 |
陷阱:dict.fromkeys(["a", "b"], []) 会让所有 key 指向同一个空列表!要独立列表用推导式:{k: [] for k in keys}。
三、增删改查
查
1 | d = {"name": "咖飞", "age": 3} |
规则:确定 key 存在用 d[k],可能不存在用 d.get(k)。前者更快,后者更安全。
改与增
1 | d["age"] = 4 # 修改已有 key |
Python 3.9+ 还有合并运算符 |:
1 | a = {"x": 1, "y": 2} |
删
1 | d = {"a": 1, "b": 2, "c": 3} |
四、遍历字典
1 | score = {"张三": 90, "李四": 85, "王五": 78} |
keys / values / items 是视图
它们不是列表,是动态视图——字典变,它们也跟着变:
1 | d = {"a": 1, "b": 2} |
需要真正的列表用 list(d.keys())。
注意:遍历字典时不能修改字典结构(增删 key):
1 | for k in d: |
正确做法:遍历 list(d) 或用推导式重建:
1 | d = {k: v for k, v in d.items() if v != 1} |
五、Python 3.7+ 有序性保证
Python 3.7 起,dict 官方保证按插入顺序遍历:
1 | d = {} |
3.6 里 CPython 已经这样实现了,但只是”实现细节”;3.7 才写进语言规范。之前需要有序字典要用 collections.OrderedDict,现在不需要了,除非你需要 OrderedDict 独有的 move_to_end 方法。
六、字典常用方法速查
1 | d = {"a": 1, "b": 2} |
七、字典推导式
推导式(第 15 篇讲)也适用于字典:
1 | # 平方表 |
八、嵌套字典
字典的值可以是任何对象,包括字典本身:
1 | users = { |
深层嵌套的取值和赋值容易出 KeyError,几种应对:
1 | # 1. 逐层 get |
九、defaultdict:自动生成缺失值
collections.defaultdict 是字典的增强版:访问不存在的 key 时自动创建:
1 | from collections import defaultdict |
十、Counter:计数专用字典
collections.Counter 是专为计数设计的字典:
1 | from collections import Counter |
十一、字典作为高性能查找表
字典的 x in d 和 d[x] 都是 平均 O(1),比列表的线性查找快得多。所以大量存在性判断或映射查找请优先用字典或集合。
1 | # ❌ O(n * m):慢 |
十二、性能与内存
- 每个 dict 起步内存约 200-300 字节;
- 存储 1 亿个 int→int 大约 5-10GB,别指望在 8GB 内存里塞进去;
- Python 3.6 起 dict 内存布局做过优化,比早期版本省 20%-25%;
- 大量小 dict 场景可以考虑
dataclass(slots) 或者 namedtuple。
十三、一个综合例子:词频统计器
1 | # wordfreq.py |
十四、常见陷阱
- 可变对象做 key:
d[[1, 2]] = "x"→ TypeError,list 不可哈希。用元组(1, 2)。 - 同一 key 被覆盖:
{"a": 1, "a": 2}结果是{"a": 2},不会警告。 dict.fromkeys(..., [])共享列表:改一个动全部。- 遍历中修改字典:会抛 RuntimeError。遍历
list(d)或d.copy()。 - 拷贝浅:
d2 = d1.copy()是浅拷贝,嵌套字典/列表要用copy.deepcopy。 - Python 3.7 前顺序不保证:老代码依赖顺序的话检查一下 Python 版本。
in只查 key:判断 value 是否存在要x in d.values()。
十五、小结与延伸阅读
- 字典是最常用的容器之一,几乎所有映射场景都用它;
- key 必须可哈希,value 任意;
get / setdefault / update / pop是最常用的方法;- Python 3.7+ 保证插入顺序;
keys/values/items是视图,不是列表;- 遍历中不要修改字典结构;
collections.defaultdict / Counter / OrderedDict是字典家族的强力扩展;- 大批量查找永远用 dict/set 而不是 list。
延伸阅读:
- 官方 dict 文档:https://docs.python.org/zh-cn/3/library/stdtypes.html#dict
- collections 家族:https://docs.python.org/zh-cn/3/library/collections.html
下一篇 集合 Set 与集合运算 我们讲字典的兄弟——集合。