Python字典(dict)按键存值:你提供键,它返回对应的值,不必像列表那样先记住下标。键必须唯一且可哈希,值可以是任意对象,包括列表和另一层字典。配置项、接口返回的 JSON、按姓名查成绩这类按名字找数据的场景,字典几乎是默认选择。
键到值的映射
字面量用大括号写成 键: 值。同一个键只能留一份,后写入的值会盖住先前的。查找时写 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 负责删掉某个键并返回它的值,第二个参数同样可以在键缺失时充当退路:
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。 - 键必须可哈希,所以列表不能当键,元组可以。
- 同一键写两次时,留下的是后一次的值。
- 嵌套写入前要先确认中间层已经存在。