Maya 想知道最好賣的飲料、正在排隊的訂單,還有按杯型統計的數量。三個迴圈也能做,三個容器做得更清楚。哪個容器不用 dict.get 就能計數?
collections 模組為常見任務提供專用容器:計數、按鍵分組,以及在兩端添加或刪除元素。它們各自只解決一個小問題,卻能讓程式碼意圖更清楚。 你還會保留固定長度的視窗、疊加設定,並比較庫存。
用 Counter 計數
Counter 是字典的子類,用來統計出現次數。存取不存在的鍵會回傳零,而不是拋出 KeyError。most_common 會把次數最高的項排在前面,適合做匯總和排行。
from collections import Counter
votes = ["tea", "coffee", "tea"]
counts = Counter(votes)
print(counts["tea"])
print(counts.most_common(1))先計數,再排序
用 defaultdict 分組
存取不存在的鍵時,defaultdict 會呼叫工廠函式。把 list 作為工廠,每個新鍵都會從空列表開始。這樣就不必在追加前反覆檢查鍵是否存在。
from collections import defaultdict
groups = defaultdict(list)
for name, team in [("Ada", "A"), ("Grace", "B"), ("Lin", "A")]:
groups[team].append(name)
print(dict(groups))每個新鍵都有一個列表
用 deque 操作兩端
deque 支援在兩端高效添加和刪除。popleft 從隊首移除最早的元素,append 從隊尾加入。它很適合佇列和滑動視窗。
from collections import deque
queue = deque(["a", "b"])
queue.append("c")
queue.popleft()
print(list(queue))雙端佇列
保留固定長度的滾動視窗
帶 maxlen 的 deque 會自動丟掉最舊的元素,很適合移動平均或短活動流:不用切片複製,也不用維護索引。視窗大小在建立 deque 時就固定下來。
from collections import deque
window = deque(maxlen=3)
for reading in [10, 12, 11, 15]:
window.append(reading)
print(list(window), round(sum(window) / len(window), 1))新值進來,舊值自動離開
用 ChainMap 疊加設定
ChainMap 從左到右尋找各個映射。把使用者設定放前面、預設值放後面,使用者沒有設定的鍵會自動落到預設層,不需要複製合併整本字典。new_child() 可以為一個請求或一個頁面建立臨時覆蓋層。
from collections import ChainMap
defaults = {"theme": "light", "page_size": 20}
user = {"theme": "dark"}
settings = ChainMap(user, defaults)
print(settings["theme"], settings["page_size"])
print("page_size" in user)
scoped = settings.new_child({"page_size": 50})
print(scoped["page_size"], settings["page_size"])不複製字典也能覆蓋
Counter 運算只保留正庫存
兩個 Counter 相減時,零和負數會被丟掉。用來算剩餘庫存很方便,但結果不再是完整帳本。交集 & 對每個鍵保留較小的計數,回答的是另一個問題:兩份庫存有多少共同部分?
from collections import Counter
stock = Counter({"tea": 3, "latte": 2})
sold = Counter({"tea": 2, "latte": 2, "mocha": 1})
left = stock - sold
print(left)
print(list(left.elements()))
print(stock & sold)剩餘庫存和共同庫存不是一回事
本課要點
- Counter 統計可雜湊值,缺失鍵回傳零。
- most_common 按次數從高到低排序。
- defaultdict 會為缺失鍵建立預設值。
- deque 支援高效的兩端操作。
- 離開局部程式碼時,可以把專用容器轉換成普通列表或字典。
- 滾動視窗用 maxlen,設定優先級用 ChainMap,庫存視圖用 Counter 運算。
常見錯誤
- 鍵可能不存在時,仍然對普通字典使用 counts[key]。
- 忘記 defaultdict 在讀取時也會插入鍵。
- 需要佇列時反覆使用 list.pop(0),而沒有考慮 deque。
- 把 Counter 相減當成完整審計記錄:零和負數結果會消失。
用 Counter 統計 ['a', 'b', 'a'],再往 defaultdict(list) 裡添加一個新團隊。
動手試試
改改變數、先預測輸出,再執行程式碼。第一次點擊「執行程式碼」時會下載 Python 執行時,可能需要幾秒鐘。
練習本課
12 道題,作答後立即看到解釋。