Python字典默认值处理:避免KeyError异常的实用技巧

大家都知道,在 Python 里要是去访问字典中不存在的键,就会导致 KeyError 异常。像下面这样的例子:
strings = ('puppy', 'kitten', 'puppy', 'puppy',
'weasel', 'puppy', 'kitten', 'puppy')
counts = {}
for kw in[id_242523718]
counts[kw] += 1
该例子会统计 strings 中某个特定单词出现的频次,并在 counts 字典里进行记录。每当这个单词出现一次,counts 中与之对应的键所存储的值的数字就会加 1。然而实际上,运行这段代码时会引发 KeyError 异常,其出现的时机是在对每个单词进行首次统计的时候,原因是在 Python 的 dict 中不存在默认值这一说法。
counts = dict()
counts
Out[13][id_1716128838] {}
counts['puppy'] += 1
Traceback (most recent call last):
File "" , line 1, in <module>
counts['puppy'] += 1
KeyError: 'puppy'
进行检查时使用判断语句。这样的话,首先能想到的办法是在对单词进行第一次统计的时候,在 counts 中把相应的键存入默认值 1 。这就需要在处理过程中添加一个判断语句:
strings = ('puppy', 'kitten', 'puppy', 'puppy',
'weasel', 'puppy', 'kitten', 'puppy')
counts = {}
for kw in strings:
if kw not in counts:
counts[kw] = 1
else:
counts[kw] += 1
counts
Out[16]: {'kitten': 2, 'puppy': 5, 'weasel': 1}
2、使用dict.setdefault()方法来设置默认值
将counts[‘ooo’]赋予初始值
counts = {}
counts.setdefault('ooo',5)
Out[2]: 5
counts
Out[3]: {'ooo': 5}
统计不同的值的次数
strings = ('puppy', 'kitten', 'puppy', 'puppy',
'weasel', 'puppy', 'kitten', 'puppy')
counts = {}
for kw in strings:
counts.setdefault(kw, 0)
counts[kw] += 1
dict.setdefault()方法的返回值能够对 for 循环中的代码进行重写,让其变得更加简洁。
strings = ('puppy', 'kitten', 'puppy', 'puppy',
'weasel', 'puppy', 'kitten', 'puppy')
counts = {}
for kw in strings:
如果 counts 中存在 kw 这个键,那么 counts[kw] 就等于 counts[kw] 本身;如果 counts 中不存在 kw 这个键,那么 counts[kw] 就等于 0 。0) + 1
3、使用collections.defaultdict
defaultdict 类类似于一个 dict 。它具有这样的特点:是使用一个类型来进行初始化的。
from从 collections 模块中导入 defaultdict 。
dd = defaultdict(list)
dd
Out[19]: defaultdict(list, {})
defaultdict 类的初始化函数会接受一个类型作为参数。当所访问的键不存在时,它能够实例化一个值作为默认值。
dd['foo']
Out[25]: []
dd
Out[26]: defaultdict(list, {'foo': []})
dd['bar'].append('quux')
dd
Out[28]: defaultdict(list, {'bar': ['quux'], 'foo': []})
defaultdict 类不仅能够接受类型名称作为初始化函数的参数,还可以运用任何一个没有参数的可调用函数。在这种情况下,该函数的返回结果会被当作默认值,从而让默认值的取值变得更加灵活。以下通过一个例子来阐释,怎样把自定义的不带参数的函数 zero()当作 defaultdict 类的初始化函数的参数:
from collections import defaultdict
def zero():
return 0
dd = defaultdict(zero)
dd
Out[31]: defaultdict(, {})
dd['foo']
Out[32]: 0
如果使用 lambda 匿名函数,即 lambda: 0 ,那么它会返回函数结果 0 值。
from collections import defaultdict
strings = ('puppy', 'kitten', 'puppy', 'puppy', 'weasel', 'puppy', 'kitten', 'puppy')
counts = defaultdict(lambda: 0) # 使用lambda来定义简单的函数
for s in strings:
counts[s] += 1
counts
Out[40]:
defaultdict(lambda>>,
{'kitten': 2, 'puppy': 5, 'weasel': 1})