引言
情况是这样的:
我们有一个数字列表,我们想找到列表中每个数字出现的次数。
通常的做法是创建一个包含所有可能数字的键的字典,然后将它们都递增。
仔细看下面的代码片段:
if number not in dict_: dict_[number] = 0
注意,我们必须先检查该值是否在字典中不存在,然后再为其分配值。如果不执行此步骤,则在增加键数时会出错。
一个错误的例子:
>>> mydict = {}>>> mydict[1]Traceback (most recent call last): File "<pyshell#1>", line 1, in <module> mydict[1]KeyError: 1>>>
当相应的键在字典中不存在时,就会发生上述错误。
代码的结果是:
{7: 3, 2: 9, 4: 5, 5: 3, 10: 1, 9: 2, 8: 3, 3: 1, 1: 2, 6: 1}
但是我们肯定可以做得更好。
defaultdict
defaultdict 通过建立在字典之上来处理我们先前的错误。它不像常规词典一样给出一个 KeyError。但是,每当你尝试访问或“分配”不存在的密钥时,它将创建该密钥并为其提供一个已指定的默认值。
让我们来试一试:
from collections import defaultdict
defaultdict 是来自 collections 包的库。
def default_value():return "Not Present Yet"
defaultdict 需要一个函数来告诉它,如果键最初不存在,该函数将其分配为值。在这种情况下,“Not Present Yet”将是该默认值:
mydict = defaultdict(default_value)
defaultdict 接受一个参数: 返回默认值的函数的名称。
现在我们来分配默认字典中的值:
mydict["cat"] = 2mydict["dog"] = 4
让我们尝试调用这些键并得到它们对应的值:
print(mydict["cat"])print(mydict["dog"])
输出:
24
到目前为止,我们看到它与普通字典没有什么不同。
现在让我们尝试查找添加的未分配的条目:
print(mydict["pig"])print(mydict["rabbit"])
输出:
24Not Present YetNot Present Yet
对于未分配的两个条目,它返回 Not Present Yet。
如果我们打印出 mydict 的内容,你会注意到 pig 和 dog 被赋予了 Not Present Yet 的值:
defaultdict(<function default_value at 0x0000019579608708>, {'cat': 2, 'dog': 4, 'pig': 'Not Present Yet', 'rabbit': 'Not Present Yet'})
同样,每当你尝试访问或“分配”一个不存在的键时,它将创建该键并给它一个已经指定的默认值。
默认值为 Not Present Yet。这将被分配给不在默认字典中的密钥。
完整代码:
在上面的代码中,default_value 这个函数只使用了一次,所以我们可以使用 lambda,如下所示:
mydict = defaultdict(lambda: "Not Present Yet" )
现在我们已经了解了 defaultdict,我们可以在下面的代码片段中试用它们。
原代码:
现在,使用 defaultdict :
由于使用了 defaultdict ,因此我们能够缩短并简化上面的实现。
为了避免 KeyError 错误,我们不必检查我们的值是否存在,而是简单地允许默认字典执行它们的操作。它会自动将0分配给任何键。
注意:defaultdict(lambda: 0)有一个简写方式,那就是defaultdict(int),是不是又方便了许多~
总结
正如你所看到的,defaultdict 已被证明是字典的一个有用的替代选择。试试上面的例子,然后自己测试一下。