Python字典(dict)按键存值:你提供键,它返回对应的值,不必像列表那样先记住下标。键必须唯一且可哈希,值可以是任意对象,包括列表和另一层字典。配置项、接口返回的 JSON、按姓名查成绩这类按名字找数据的场景,字典几乎是默认选择。

键到值的映射

字面量用大括号写成 键: 值。同一个键只能留一份,后写入的值会盖住先前的。查找时写 person["name"],走的是键,而不是第几个元素:

键 key(唯一) 值 value "name" 小明 "age" 20 "city" 北京
字典不靠顺序找,靠键找值:person["name"] 直接取到 小明。键唯一、可哈希,值可以是任何类型。
person = {"name": "小明", "age": 20, "city": "北京"}
print(person["name"])    # 小明
print(person["age"])     # 20

几种创建方式

空字典是 {}dict()。除了字面量,还可以把关键字参数交给 dict,或传入一组 (键, 值) 对。关键字参数那种写法里,键必须是合法标识符,复杂键还是用字面量或键值对列表更合适:

a = {}
b = {"apple": 5, "banana": 3}
c = dict(name="Tom", age=18)
d = dict([("a", 1), ("b", 2)])

print(b, c, d)
print(type(a))           # <class 'dict'>

增删改查

方括号赋值时,键不存在就新增,已存在就覆盖。读取时若键不存在,d["x"] 会抛 KeyError。拿不准键在不在,用 get:默认得到 None,也可以自己指定缺省值。pop 负责删掉某个键并返回它的值,第二个参数同样可以在键缺失时充当退路:

Python 字典增改查与删除示例运行
d = {"a": 1, "b": 2}
d["c"] = 3
d["a"] = 100
print(d)                 # {'a': 100, 'b': 2, 'c': 3}

print(d["a"])            # 100
# print(d["x"])          # KeyError

print(d.get("x"))        # None
print(d.get("x", "缺省"))

d.pop("b")
print(d)                 # {'a': 100, 'c': 3}
print(d.pop("zzz", "没有"))

遍历字典

直接 for k in d 遍历的是键。只要值,用 values()。键和值一起处理,用 items(),循环里可以顺手解包成两个名字:

d = {"name": "Tom", "age": 18}

for k in d:
    print(k, end=" ")          # name age
print()

for v in d.values():
    print(v, end=" ")          # Tom 18
print()

for k, v in d.items():
    print(f"{k}={v}", end=" ") # name=Tom age=18
print()

从 Python 3.7 起,字典会保留插入顺序,遍历时一般按写入先后出现,但这和用下标取第 n 项不是同一回事,定位数据仍然应当靠键。

键的判断与排序

in 判断的是键是否存在,不会去扫一遍值。若输出时希望按键名排好再列,可以对键做 sorted,再拿排序后的键去取值:

d = {"banana": 3, "apple": 5, "cherry": 1}
print("apple" in d)            # True
print("banana" in d.keys())    # True

for k in sorted(d):
    print(k, d[k], end=" | ")  # apple 5 | banana 3 | cherry 1
print()

嵌套字典

值的位置可以再放字典或列表,于是能表达分层结构。访问时从外向内写键,遇到列表再接下标。向还不存在的内层写入前,要先把中间那一层建出来,否则会在外层键上直接触发 KeyError

school = {
    "class1": {"人数": 30, "班主任": "张老师"},
    "class2": {"人数": 28, "班主任": "李老师"},
}

print(school["class1"]["班主任"])   # 张老师

menu = {"soup": ["番茄汤", "酸辣汤"], "main": ["米饭", "面条"]}
print(menu["main"][1])             # 面条

先写 d["new"] = {} 再往里填,或使用下一篇的 setdefault,都能避免中间层还没建好就取值的问题。

注意事项

  • 键缺失时方括号读取会报 KeyError,不确定有没有这个键就用 get
  • 键必须可哈希,所以列表不能当键,元组可以。
  • 同一键写两次时,留下的是后一次的值。
  • 嵌套写入前要先确认中间层已经存在。