Kodewick
第 11 课,共 31 课目录

字典

第 11 课,共 31 课 · 第 2 部分 · 容器和循环 · 约 15 分钟

列表按位置找东西:第 0 项、第 1 项。字典按名字找东西。它存的是一对一对的:一个键,和配着它的值。写在花括号里,每对写成 键: 值,用逗号隔开。

main.py
1stock = {"煤": 40, "铁": 12, "金": 3}2print(stock)3print(stock["铁"])4print(len(stock))5print(type(stock))
输出
{'煤': 40, '铁': 12, '金': 3}
12
3
<class 'dict'>

可以把它想成仓库的账本:查 "铁",读到 12。len 数的是有几对。键一般是字符串,数字也行;值什么都能放,列表也可以。

查一个值

字典[键] 给出这个键的值。键要一模一样:"Iron" 和 "iron" 是两个不同的键。要一个不存在的键,Python 会停下来,报 KeyError,并说出缺的是哪个键。

main.py
1stock = {"煤": 40, "铁": 12, "金": 3}2print(stock["金"])3print(stock["银"])
输出
3
Traceback (most recent call last):
  File "main.py", line 3, in <module>
    print(stock["银"])
KeyError: '银'

发生了什么: 字典里没有 '银' 这个键。

in 查的是某个键在不在字典里,不看值。

main.py
1stock = {"煤": 40, "铁": 12, "金": 3}2print("煤" in stock)3print(40 in stock)4if "银" in stock:5    print(stock["银"])6else:7    print("还没有银")
输出
True
False
还没有银

get():安全地取值

get(键) 和 字典[键] 差不多,只是键不存在时给 None,不报错。再给它第二个值,键不存在时就给这个值,而不是 None。

main.py
1stock = {"煤": 40, "铁": 12}2print(stock.get("煤"))3print(stock.get("银"))4print(stock.get("银", 0))
输出
40
None
0

键一定该在的时候,用 字典[键],写错了会马上报错。键不在也正常的时候,用 get。

添加和修改

字典[键] = 值 做两件事:键是新的,就加一对;键已经有了,就换掉它的值。同一个键只能出现一次。

main.py
1stock = {"煤": 40}2stock["铁"] = 123print(stock)4stock["煤"] = 355print(stock)6stock["煤"] = stock["煤"] + 57print(stock)8stock.update({"金": 3, "铁": 20})9print(stock)
输出
{'煤': 40, '铁': 12}
{'煤': 35, '铁': 12}
{'煤': 40, '铁': 12}
{'煤': 40, '铁': 20, '金': 3}

update 从另一个字典里一次加上或换掉好几对。字典记得键加进来的顺序;改一个值不会让它换位置。

删除

del 字典[键] 删掉一对。pop(键) 删掉它并返回它的值。键不存在时两个都会报 KeyError,除非给 pop 第二个值,拿它来代替。

main.py
1stock = {"煤": 40, "铁": 12, "金": 3}2del stock["煤"]3print(stock)4gold = stock.pop("金")5print(gold, stock)6print(stock.pop("银", 0))
输出
{'铁': 12, '金': 3}
3 {'铁': 12}
0

clear() 把整个字典清空。

keys、values、items

keys() 给出所有的键,values() 所有的值,items() 所有的对,每对是一个 (键, 值) 元组。套上 list() 就能看成普通的列表。sum、max、sorted、in 也都能用在上面。

main.py
1stock = {"煤": 40, "铁": 12, "金": 3}2print(list(stock.keys()))3print(list(stock.values()))4print(list(stock.items()))5print(f"矿石总数:{sum(stock.values())}")6print(sorted(stock))
输出
['煤', '铁', '金']
[40, 12, 3]
[('煤', 40), ('铁', 12), ('金', 3)]
矿石总数:55
['煤', '金', '铁']

sorted(stock) 排的是键:直接拿字典来用时(比如 in、sorted),用到的是它的键。第 13 课的 for 循环会一对一对地把它们走一遍。

先猜一猜

这段会显示什么?

1d = {"a": 1, "b": 2}2d["a"] = 33d["c"] = 14print(len(d), sum(d.values()))

用字典计数

字典天生适合记数:东西当键,次数当值。诀窍是 get(键, 0) + 1:第一次出现时 get 给 0,于是从 1 开始数。

main.py
1found = "铁 煤 铁 金 铁".split()2counts = {}3counts[found[0]] = counts.get(found[0], 0) + 14counts[found[1]] = counts.get(found[1], 0) + 15counts[found[2]] = counts.get(found[2], 0) + 16print(counts)
输出
{'铁': 2, '煤': 1}

点单步,看 counts 一点点变多:先出现 铁,再出现 煤,然后 铁 变成 2。一个词写一行太长了;第 13 课用 for 循环,两行就能数完任意多个词。

小技巧: counts.get(word, 0) + 1 不管这个词出现过没有都能用。换成 counts[word] + 1,第一次就会报 KeyError。

什么能当键

键必须是不能改的值:字符串、数字、布尔值,或者由它们组成的元组。列表能改,所以不能当键。Python 把这种值叫作不可哈希(unhashable)。

main.py
1lamps = {(4, 7): "亮", (2, 3): "暗"}2print(lamps[(4, 7)])3bad = {["煤"]: 1}
输出
亮
Traceback (most recent call last):
  File "main.py", line 3, in <module>
    bad = {["煤"]: 1}
TypeError: unhashable type: 'list'

发生了什么: 列表不能当字典的键,键要用字符串或数字。

值没有这个限制。值可以是列表,甚至是另一个字典。

方法一览

写法作用
d[k]k 的值(没有就报 KeyError)
d.get(k) / d.get(k, x)值;没有就给 None / x
d[k] = v加上这一对,或者换掉值
d.update(other)加上或换掉 other 里的每一对
del d[k]删掉这一对
d.pop(k) / d.pop(k, x)删掉并返回值;没有就返回 x
d.clear()全部删掉
k in dk 是不是一个键
d.keys()、d.values()、d.items()所有键、所有值、所有 (键, 值) 对
len(d)有几对

练一练

写好代码,点检查。提示随便看,实在想不出来再看答案。

练习 1

来了一车货

一辆车又送来 8 块铁,还有第一批 5 块银。改一改 stock,让它显示下面这样。

要显示
{'煤': 40, '铁': 20, '银': 5}
exercise1.py
1stock = {"煤": 40, "铁": 12}2# 在这里写3print(stock)
输出
点「运行」或按 Ctrl+Enter
练习 2

客气地问

显示每条街有几盏灯。字典里没有山坡街,应该显示 0,而且不报错。

要显示
2
0
exercise2.py
1lamps = {"磨坊巷": 4, "池塘路": 2}2print(lamps["池塘路"])3print(lamps["山坡街"])
输出
点「运行」或按 Ctrl+Enter
练习 3

数矿石

用 get 把三次挖到的东西数进 counts,然后显示出来。

要显示
{'金': 2, '煤': 1}
exercise3.py
1finds = ["金", "煤", "金"]2counts = {}3# 在这里写4print(counts)
输出
点「运行」或按 Ctrl+Enter

这一课学会了

  • 字典存的是 键: 值 对:{"煤": 40}。d[键] 查值。
  • 键不存在会报 KeyError;get(键, 默认值) 可以避开。in 查的是键。
  • d[键] = 值 添加或修改;del、pop、clear 删除。
  • keys()、values()、items() 给出键、值和一对对的元组。
  • d[k] = d.get(k, 0) + 1 用来计数。
  • 键必须是不能改的值,比如字符串、数字、元组,列表不行。