字典
列表按位置找东西:第 0 项、第 1 项。字典按名字找东西。它存的是一对一对的:一个键,和配着它的值。写在花括号里,每对写成 键: 值,用逗号隔开。
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,并说出缺的是哪个键。
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 查的是某个键在不在字典里,不看值。
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。
1stock = {"煤": 40, "铁": 12}2print(stock.get("煤"))3print(stock.get("银"))4print(stock.get("银", 0))
40 None 0
键一定该在的时候,用 字典[键],写错了会马上报错。键不在也正常的时候,用 get。
添加和修改
字典[键] = 值 做两件事:键是新的,就加一对;键已经有了,就换掉它的值。同一个键只能出现一次。
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 第二个值,拿它来代替。
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 也都能用在上面。
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()))
d["a"] = 3 换掉的是 "a" 的值,不会多加一对。所以一共三个键 a、b、c,值加起来是 3 + 2 + 1 = 6。
用字典计数
字典天生适合记数:东西当键,次数当值。诀窍是 get(键, 0) + 1:第一次出现时 get 给 0,于是从 1 开始数。
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)。
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 d | k 是不是一个键 |
d.keys()、d.values()、d.items() | 所有键、所有值、所有 (键, 值) 对 |
len(d) | 有几对 |
练一练
写好代码,点检查。提示随便看,实在想不出来再看答案。
来了一车货
✓一辆车又送来 8 块铁,还有第一批 5 块银。改一改 stock,让它显示下面这样。
{'煤': 40, '铁': 20, '银': 5}1stock = {"煤": 40, "铁": 12}2# 在这里写3print(stock)
客气地问
✓显示每条街有几盏灯。字典里没有山坡街,应该显示 0,而且不报错。
2 0
1lamps = {"磨坊巷": 4, "池塘路": 2}2print(lamps["池塘路"])3print(lamps["山坡街"])
数矿石
✓用 get 把三次挖到的东西数进 counts,然后显示出来。
{'金': 2, '煤': 1}1finds = ["金", "煤", "金"]2counts = {}3# 在这里写4print(counts)
这一课学会了
- 字典存的是
键: 值对:{"煤": 40}。d[键]查值。 - 键不存在会报
KeyError;get(键, 默认值)可以避开。in查的是键。 d[键] = 值添加或修改;del、pop、clear删除。keys()、values()、items()给出键、值和一对对的元组。d[k] = d.get(k, 0) + 1用来计数。- 键必须是不能改的值,比如字符串、数字、元组,列表不行。