你嚴重低估了defaultdict的偷懶能力!
字典作為日常使用頻率較高的一種數(shù)據(jù)類型,常會遇到判斷key是否在字典中的情況。
這時,我們是否按照如下代碼寫的:
d = dict()
if 'key' in d:
d['key'] += 1
else:
d['key'] = 0
print(d['key']) # 1
我們每次都需要判斷后再進行相關操作。
但是,當我們使用了defaultdict后,就可以偷懶的簡化if else 的格式了:
from collections import defaultdict
d = defaultdict(int)
d["key"] += 1
print(d['key']) # 1
關于defaultdict
大家日常使用到defaultdict的場景,絕大多數(shù)都是上述舉例為了減少if else的判斷。
當然除了默認的int初始化,還有列表追加 d = defaultdict(list) 的無腦append操作。
可是,我們是否有深挖過defaultdict的其他場景呢?來先看看它的源碼:
源碼注釋中,只是簡單說明了使用default_factory參數(shù),可以讓調用鍵不存在時生成新值。
def __init__(self, default_factory=None, **kwargs):
# known case of _collections.defaultdict.__init__
"""
defaultdict(default_factory=None, /, [...]) -->
dict with default factory
The default factory is called without arguments to produce
a new value when a key is not present, in __getitem__ only.
A defaultdict compares equal to a dict with the same items.
All remaining arguments are treated the same as if they were
passed to the dict constructor, including keyword arguments.
# (copied from class doc)
"""
pass
就比如我們上面 defaultdict(int) 將key不存在時,value默認賦值0, d = defaultdict(list) 將key不存在時,value默認賦值空列表。
聽起來功能就是如此了吧...
現(xiàn)在我們來換個場景,拿同學們打力扣周賽舉個例子。
力扣周賽
每個人參加力扣周賽時,會根據(jù)我們的比賽結果進行評分。如果是第一次參加比賽,因為沒有初始積分,從0分開始不太合適。
所以每位選手的初始基準分為1500分。這樣就可以根據(jù)選手分數(shù)來考量本次比賽表現(xiàn)進行加分了。
先來看看默認字典的代碼應該如何操作:
scores = dict()
add_score = 10
# 方法1
if 'xiaoming' in scores:
scores['xiaoming'] += add_score
else:
scores['xiaoming'] = 1500 + add_score
# 方法2
scores['xiaoming'] = scores.get('xiaoming', 1500) + add_score
現(xiàn)在我們想使用defaultdict,但defaultdict如果賦值int,就沒辦法提供這個基準分了,該如何是好?
此時我們應該深入理解下 default_factory ,它不僅僅支持我們傳入默認的int、list,還支持我們使用自定義函數(shù)。
from collections import defaultdict
def diy_func():
print("init user score.")
return 1500
scores = defaultdict(diy_func)
scores['xiaoming'] += 10
print(scores['xiaoming'])
# init user score.
# 1510
我們通過自定義一個函數(shù)賦值給 default_factory, 幫我們初始化用戶的分數(shù)。
但這個自定義的函數(shù)方法有些太過單一了,是否可以簡化?此時我們應該考慮到lambda表達式??!
scores = defaultdict(lambda: 1500)
scores['xiaoming'] += 10
print(scores['xiaoming'])
這樣做是不是就更簡潔方便了。有沒有覺得這操作很nice?
然而,我們注意到defaultdict的 __init__ 方法是存在 **kwargs** 參數(shù),我們還沒有使用呢!
它還可以這么玩:
from collections import defaultdict
data = defaultdict(xiaozhang=1600, xiaowang=1700)
scores = defaultdict(lambda: 1500, data)
scores['xiaoming'] += 10
scores['xiaowang'] -= 15
print(scores.items())
# dict_items([('xiaozhang', 1600), ('xiaowang', 1685), ('xiaoming', 1510)])
所以,defaultdcit可以在 使用 default_factory 的基礎上,導入初始的字典進行。是不更溜了?
關于default_dict的內容,今天就學到這里吧,希望對大家有所幫助。