Python 新手到進階:玩轉 collections.defaultdict 的正確姿勢

加入好友
加入社群
Python 新手到進階:玩轉 collections.defaultdict 的正確姿勢 - 儲蓄保險王

什麼是 defaultdict

defaultdict 是 Python 標準庫 collections 裡的一種字典(dict)子類。
它解決了一個常見問題:存取不存在的 key 時不會報錯,還能自動幫你建立預設值!


為什麼要用 defaultdict

假設你要做一個字典,統計每個字母出現次數,普通寫法如下:

counts = {}
for ch in 'banana':
    if ch not in counts:
        counts[ch] = 0
    counts[ch] += 1

這種寫法很常見,但每次都要檢查 key 是否存在。


defaultdict 的超簡潔寫法

from collections import defaultdict

counts = defaultdict(int)  # int() 預設值是 0
for ch in 'banana':
    counts[ch] += 1

print(counts)  # defaultdict(<class 'int'>, {'b': 1, 'a': 3, 'n': 2})

輸出結果:

Python 新手到進階:玩轉 collections.defaultdict 的正確姿勢 - 儲蓄保險王

優點:不用再判斷 key 是否存在!


defaultdict 的常見用法

1. 統計次數

words = ['cat', 'dog', 'cat', 'dog', 'cat', 'fish']
counter = defaultdict(int)
for word in words:
    counter[word] += 1
print(counter)

輸出結果:

Python 新手到進階:玩轉 collections.defaultdict 的正確姿勢 - 儲蓄保險王

2. 統計多個值(如字典的 value 是 list)

group = defaultdict(list)
for name, group_id in [('Amy', 1), ('Ben', 2), ('Carl', 1)]:
    group[group_id].append(name)
print(group)  # defaultdict(<class 'list'>, {1: ['Amy', 'Carl'], 2: ['Ben']})

輸出結果:

Python 新手到進階:玩轉 collections.defaultdict 的正確姿勢 - 儲蓄保險王

3. 巢狀結構(自動建多層 dict)

初階寫法(只能一層)

d = defaultdict(dict)
d['a']['b'] = 1  # 只會自動建立 'a' 這一層
# d['a']['b']['c'] = 2  # 會報錯因為 d['a']['b'] 只是普通 dict

輸出結果:

Python 新手到進階:玩轉 collections.defaultdict 的正確姿勢 - 儲蓄保險王

進階:無限巢狀 defaultdict

def tree():
    return defaultdict(tree)

nested = tree()
nested['foo']['bar']['baz'] = 123
print(nested['foo']['bar']['baz'])  # 123

輸出結果:

Python 新手到進階:玩轉 collections.defaultdict 的正確姿勢 - 儲蓄保險王

如何把 defaultdict 轉回普通 dict(遞迴轉換)

defaultdict 不是序列化友善的類型,如果你要 dump 成 JSON,
可以用遞迴方式轉成普通 dict:

# 沒有 else
def to_dict(d):
    if isinstance(d, defaultdict):
        return {k: to_dict(v) for k, v in d.items()}
    return d

#  else,邏輯比較清楚
def to_dict(d):
    if isinstance(d, defaultdict):
        return {k: to_dict(v) for k, v in d.items()}
    else:
        return d

實證:

Python 新手到進階:玩轉 collections.defaultdict 的正確姿勢 - 儲蓄保險王

實用場景小結

  • 字頻/計數統計(int)
  • 群組分桶(list/set)
  • 多層巢狀資料(遞迴 tree)

小提示

  • defaultdict(int) → 預設 0
  • defaultdict(list) → 預設空列表
  • defaultdict(set) → 預設空集合
  • defaultdict(lambda: 'Hello!') → 預設自定義值

結論

defaultdict 是 Pythonic 寫法的好幫手,
讓你的程式更簡潔、更健壯、更易維護!

推薦hahow線上學習python: https://igrape.net/30afN

nested = defaultdict(defaultdict) #無法無限遞迴

實際上不能達到「多層巢狀自動建立」的效果!


為什麼?

因為:

  • defaultdict(defaultdict) 的意思是:當 key 不存在時,會呼叫「預設工廠」defaultdict()
  • 沒給 defaultdict 的型別參數,所以會報錯:
Python 新手到進階:玩轉 collections.defaultdict 的正確姿勢 - 儲蓄保險王
  • 更重要的是,即使你寫成 defaultdict(dict)
    只會自動建立一層普通 dict,下一層不會是 defaultdict!

正確的遞迴巢狀 defaultdict 寫法

你應該用函式遞迴來建立每一層:

from collections import defaultdict

def tree():
    return defaultdict(tree)

nested = tree()
nested['a']['b']['c'] = 123  # 每層都自動建立

輸出結果:

Python 新手到進階:玩轉 collections.defaultdict 的正確姿勢 - 儲蓄保險王

小結

  • defaultdict(defaultdict) ❌ 錯誤寫法,不支援多層自動巢狀
  • defaultdict(dict) ❌ 只會自動建立一層
  • defaultdict(tree) ✅ 無限巢狀,推薦

視覺化差異

Python 新手到進階:玩轉 collections.defaultdict 的正確姿勢 - 儲蓄保險王

重點:要實現多層巢狀自動建立,必須用遞迴函式當工廠,不是直接 defaultdict(defaultdict)。

推薦hahow線上學習python: https://igrape.net/30afN

加入好友
加入社群
Python 新手到進階:玩轉 collections.defaultdict 的正確姿勢 - 儲蓄保險王

儲蓄保險王

儲蓄險是板主最喜愛的儲蓄工具,最喜愛的投資理財工具則是ETF,最喜愛的省錢工具則是信用卡

You may also like...

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *