Semorphe

字典與集合

用名字找東西,和只管有沒有。 · ⏱ 約 30 分鐘

你會學到三件事

  1. dict 用鍵找值,不是用位置
  2. set 只管「有沒有」,而且自動去重複
  3. 🔴 d["不存在"] 會出錯,d.get(...) 不會

開始之前

清單用位置找東西,而「小明的分數」不是第幾個,是一個名字。

🟢 先把編輯器打開,跟著下面一起做:跟著做

一、dict:鍵 → 值

照著打上這兩行:

1ages = {"ming": 16, "hua": 17}2print(ages["ming"])      # 16
"ming"16鍵對應"hua"17鍵對應字典變數ages"ming"取的印出設定ages為12

大括號、鍵: 值、逗號隔開。

鍵(key) 拿來找的東西——多半是文字或數字
值(value) 找到的東西——什麼都可以

🔎 這一段是試一下——打了看結果就好,不要留在程式裡。

1ages["new"] = 18         # 沒有就新增,有就覆蓋2del ages["hua"]          # 刪掉3print(len(ages))         # 幾筆
變數ages"new"取的18變數ages"hua"取的變數ages的長度印出刪掉把設成123

那一行 ages["new"] = 18 在積木上是「把 … 設成 …」—— 與第 2 課那顆「設定」不同:這一顆改的是容器裡的一格。

二、走過去

走過一本字典,拿到的是鍵:

1for k in ages:2    print(k, ages[k])
變數ages變數k變數ages變數k取的印出對裡的每一個i12

⚠️ for k in ages 走的是鍵,不是值。

想同時要鍵和值:

🔎 這一段是試一下——打了看結果就好,不要留在程式裡。

1for k, v in ages.items():2    print(k, v)
變數ages取的項目變數k變數v印出對裡的每一個k,v12
走什麼
for k in d 鍵
for v in d.values() 值
for k, v in d.items() 兩個

三、🔴 不存在的鍵

問一個不存在的鍵,它會出事:

🚫 這一段是反例——課文在說不要這樣寫,別照著拉。

1print(ages["nobody"])          # 💥 KeyError
變數ages"nobody"取的印出1

三種處理方式:

🔎 這一段是試一下——打了看結果就好,不要留在程式裡。

1if "nobody" in ages:           # ① 先問2    print(ages["nobody"])3 4print(ages.get("nobody"))          # ② None5print(ages.get("nobody", 0))       # ③ 給預設值 0
"nobody"變數ages在裡面:變數ages"nobody"取的印出變數ages"nobody"取的,取不到就用變數ages"nobody"0取的,取不到就用印出印出如果則1245

⚠️ in 對 dict 問的是「鍵在不在」,不是值。

計數的時候 get 特別好用:

🔎 這一段是試一下——打了看結果就好,不要留在程式裡。

1counts = {}2for w in words:3    counts[w] = counts.get(w, 0) + 1
字典變數words變數counts變數w取的變數counts變數w0取的,取不到就用1+把設成對裡的每一個i設定counts為123

四、set:只管有沒有

集合裡的東西不會重複:

1tags = {"a", "b", "a"}2print(len(tags))          # 2   ← 重複的自動變一個
"a""b""a"集合變數tags的長度印出設定tags為12

⚠️ set 也用大括號,分辨的方式是裡面有沒有冒號。

⚠️ {} 是空的 dict,不是空的 set。 空的 set 要寫 set()。

🔎 這一段是試一下——打了看結果就好,不要留在程式裡。

1tags.add("c")             # 加(已經有就不變)2tags.remove("a")          # 拿掉3print("b" in tags)        # True
變數tags"c"變數tags"a""b"變數tags在裡面:印出從刪掉第一個把加進集合123

它沒有順序,也不能用位置取,只回答「在不在」。

什麼時候用 set

nums = [3, 1, 4, 1, 5]
print(len(set(nums)))      # 4   ← 有幾個不同的數
print(list(set(nums)))     # 去重複

而問「在不在」的時候,set 比 list 快很多: list 要一個一個比,set 幾乎是一步到位。

完成的樣子

這一課的參考做法——程式碼每一行的號碼,就印在對應的那塊積木上。

1ages = {"ming": 16, "hua": 17}2print(ages["ming"])3ages["new"] = 184for k in ages:5    print(k, ages[k])6tags = {"a", "b", "a"}7print(len(tags))
"ming"16鍵對應"hua"17鍵對應字典變數ages"ming"取的變數ages"new"取的18變數ages變數k變數ages變數k取的印出"a""b""a"集合變數tags的長度印出設定tags為對裡的每一個i把設成印出設定ages為1234567

把積木打散,自己排回去:排回去:把剛才那支程式的積木排好

換你了

讀進一段英文,數出每個字母出現幾次,印出來。

⚠️ 裁判餵的是 aba。 ⚠️ 提示:用 counts.get(c, 0) + 1,不用先判斷那個鍵在不在。

到編輯器做這一題:練習:數出每個字母出現幾次

做一個

讀進一行英文,印出每個單字出現幾次,依字母順序。

🔴 這一題會撞到這一課那個坑:第一次看到某個字的時候,字典裡還沒有它。 ⚠️ 裁判用的是 the cat the hat the end。

到編輯器做這一題:做一個:每個字出現幾次

這一課你做了什麼

如果卡住了

你看到 多半是因為
KeyError 那個鍵不存在。用 in 或 .get()
{} 拿到的是 dict 空的 set 要寫 set()
走 dict 只拿到鍵 那就是它的行為。要值用 .items()
set 的順序每次不一樣 它本來就沒有順序
TypeError: unhashable 拿 list 當鍵了。鍵要是不可變的東西
在編輯器打開這一課 →