2017-05-17

用 Python defaultdict 解決 Dict key 不存在的問題

每次要取用 dict 時,得先檢查 key 是否存在,否則會得到 KeyError,雖然有 setdefault() 與 getdefault() 可以緩解症狀,但還是不夠直覺且有一點點的效能浪費。

常常忘記要檢查

每次取用前得先用 setdefault() 確認,不夠直覺,容易忘記。
# setdefault with int()
d = dict()

for c in 'Apple':
    d.setdefault(c, 0)
    d[c] += 1

print(d) # {'A': 1, 'p': 2, 'l': 1, 'e': 1}

可能沒必要的呼叫

就算 key 已經存在,還是會執行一次 [] 產生一個空的 list,效能浪費了。
# setdefault with list()
s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]

d = dict()

for k, v in s:
    d.setdefault(k, []).append(v)

print(sorted(d.items())) # [('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

defaultdict 來簡化

用 defaultdict 來簡化使用的過程,只要在建立 dict 時(事實上是 defaultdict)傳入 key 不存在時,用來建立 key 對應的 value 的函式即可。

defaultdict() 回傳的是 dict 的 subclass,擁有 dict 所有的功能。
# defaultdict with int()
from collections import defaultdict
d = defaultdict(int) # 表示 int(),傳入函式名稱,並未呼叫執行

for c in 'Apple':
    d[c] += 1 # 一旦遇到 key 不存在時,就會呼叫 int() 產生預設值並存入 dict 中

print(d) # defaultdict(<class 'int'>, {'A': 1, 'p': 2, 'l': 1, 'e': 1})

defaultdict 來救效能

只有 key 不存在時才會呼叫 list()。
# defaultdict with list()
s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
from collections import defaultdict
d = defaultdict(list) # 表示 list(),傳入函式名稱,並未呼叫執行

for k, v in s:
    d[k].append(v)

print(sorted(d.items())) # [('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]
dict of sets 也是常用的功能。
# defaultdict with set()
s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('red', 1), ('blue', 4)]
from collections import defaultdict
d = defaultdict(set)

for k, v in s:
    d[k].add(v)

print(sorted(d.items())) # [('blue', {2, 4}), ('red', {1, 3})]

官方文件
---
---
---

沒有留言:

張貼留言