Python collections 進階資料容器型態

Python 內建的 listdicttuple 已經非常強大,但 collections 模組提供了額外的特化容器,能讓你在處理特定邏輯時,程式碼更簡潔、效能更好。

常用容器介紹

Counter:計數器

Counter 是一個繼承自 dict 的類別,專門用來計算可雜湊物件出現的次數。

from collections import Counter

# 從字串計數
counts = Counter("hello world")
print(counts)  # Counter({'l': 3, 'o': 2, 'h': 1, 'e': 1, ' ': 1, 'w': 1, 'r': 1, 'd': 1})

# 取得出現頻率最高的第 N 個元素
print(counts.most_common(2))  # [('l', 3), ('o', 2)]

# 常見用途:計算詞頻
words = ["apple", "banana", "apple", "cherry", "banana", "apple"]
word_counts = Counter(words)
print(word_counts["apple"])  # 3

defaultdict:預設值字典

在操作字典時,如果存取不存在的鍵 (Key),會噴出 KeyErrordefaultdict 可以為不存在的鍵自動提供一個預設值。

from collections import defaultdict

# 預設值為空列表
d = defaultdict(list)

# 不需要先檢查鍵是否存在,直接 append
d['fruits'].append('apple')
d['fruits'].append('banana')

print(d['fruits'])  # ['apple', 'banana']
print(d['unknown']) # [] (自動建立一個空列表)

namedtuple:具名元組

namedtuple 讓你可以建立像物件一樣、可以透過「名稱」存取欄位的元組。比普通元組更具讀懂性,比類別 (class) 更輕量。

from collections import namedtuple

# 定義一個名為 Point 的型別,包含 'x' 和 'y' 兩個欄位
Point = namedtuple('Point', ['x', 'y'])

p = Point(10, 20)

print(p.x, p.y)  # 10 20 (透過屬性名稱存取)
print(p[0])      # 10 (仍可透過索引存取)

deque:雙向隊列

list 在前端插入或刪除元素 (pop(0)) 的效能極差(O(n))。deque (Double-ended queue) 則是為了高效的兩端操作而設計(O(1))。

from collections import deque

q = deque(['middle'])

# 在兩端新增
q.append('right')
q.appendleft('left')

print(q)  # deque(['left', 'middle', 'right'])

# 在兩端彈出
q.pop()      # 移除並回傳 'right'
q.popleft()  # 移除並回傳 'left'

實務案例:使用 Counter 與 defaultdict 分組數據

假設我們有一份學生分數列表,想統計各個等級的學生名單:

from collections import defaultdict

scores = [
    ("Alice", 85), ("Bob", 92), ("Charlie", 78),
    ("David", 85), ("Eve", 92)
]

# 按分數將姓名分組
grouped_students = defaultdict(list)
for name, score in scores:
    grouped_students[score].append(name)

print(dict(grouped_students))
# {85: ['Alice', 'David'], 92: ['Bob', 'Eve'], 78: ['Charlie']}

總結

  • Counter:快速計算頻率。
  • defaultdict:簡化字典初始化邏輯,避免 KeyError
  • namedtuple:增加程式碼可讀性,代替僅存數據的簡單類別。
  • deque:高性能的佇列 (Queue) 與堆疊 (Stack) 實現。
  • OrderedDict:保留插入順序(Python 3.7+ 的原生 dict 已具備此特性,但在某些舊代碼或特定繼承場景仍有用)。

熟練使用 collections 模組可以提升程式碼效率,也是邁向 Python 進階開發者的重要一步。