初识defaultdict
defaultdict来自于collections模块中,顾名思义,它与一般dict的不同之处在于当在取一个字典中不存在的key值时不会报错或者取到的值为None,而是会返回一个设定的默认值,例如:
# dict取不存在的key
normal_dict = dict()
print(normal_dict['a'])
>>>Traceback (most recent call last):
>>> File "test.py", line 1, in
>>> print(normal_dict['a'])
>>>KeyError: 'a'
# defaultdict取不存在的key
from collections import defaultdict
my_defaultdict = defaultdict(lambda: [])
print(my_defaultdict['a'])
>>>[]
一般来说,defaultdict中的常见参数是python中的list,str或者set等等,我之所以写一个匿名函数实际是想说明参数接受类型或者可调用函数参数,在调用一个不存的key的时候, defaultdict会调用__missing__(), 返回一个根据工厂函数返回值的默认值, 并将该键添加到字典中去,所以不会返回Keyerror。
运用defaultdict
常见的用法这里就不赘述了,虽然defaultdict可以接受一个函数作为参数,但是如果想给这个函数传参要如何做呢?比如现在我需要一个以最长长度为5的deque为默认值构造的defaultdict。解决办法是使用partial(),例如:
from functools import partial
from collections import defaultdict, deque
my_deque = partial(deque, maxlen=5)
my_defaultdict = defaultdict(my_deque)
my_defaultdict['a'].append(5)
my_defaultdict['a'].append(6)
my_defaultdict['a'].append(7)
my_defaultdict['a'].append(8)
my_defaultdict['a'].append(9)
my_defaultdict['a'].append(10)
print(dict(my_defaultdict))
>>>{'a': deque([6, 7, 8, 9, 10], maxlen=5)}
partial原本被用于减少函数的传参数量,而给某些原来的参数附上默认值,例如:
from functools import partial
def mod( n, m ):
return n % m
mod_by_100 = partial( mod, 100 )
print mod( 100, 7 ) # 2
print mod_by_100( 7 ) # 2
partial的返回值仍然是一个函数,并且将参数预先传递,所以在与defaultdict的配合使用中完美契合!
讨论
其实字典也有一个方法在没有key的情况下去给他的值设置一个默认值,那就是setdefault()方法,他与get()方法都可以在取不到key的情况下,返回一个用户定义的默认值,但是区别在于setdefault()方法会修改原字典将默认值与key配对,而get()不会,例如:
# 使用setdefault()方法
normal_dict = dict()
result = normal_dict.setdefault('a', 1)
print(result)
print(normal_dict)
>>>1
>>>{'a': 1}
# 使用get()方法
normal_dict1 = dict()
result = normal_dict1.get('a', 1)
print(result)
print(normal_dict1)
>>>1
>>>{}