defaultdict vs dict元素初始化

时间:2014-04-13 14:40:25

标签: python dictionary defaultdict

我正在尝试优化脚本的性能,该脚本在每个单词的词典中查找相似的单词。

每个唯一的单词将被分成字母n-gram,并且对于每个n-gram,词典返回包含相同字母n-gram的单词列表。然后将该列表中的每个单词作为键添加到字典中,并将其值加1。这给了我一个类似单词的词典和相应的频率分数。

word_dict = {}
get = word_dict.get
for letter_n_gram in word:
    for entry in lexicon[n_gram]:
        word_dict[entry] = get(entry, 0) + 1

此实现有效,但通过切换dict的{​​{1}},可以更快地运行脚本。

collections.defaultdict

没有其他代码被更改。

我的印象是两个代码段(最重要的是分数添加)应该以完全相同的方式工作,即如果密钥存在,则将其值增加1,如果它不存在,则创建密钥并设置值为1。

然而,在运行新代码之后,一些键的值为0,我认为这在逻辑上是不可能的。

我的word_dd = defaultdict(int) for letter_n_gram in word: for entry in lexicon[n_gram]: word_dd[entry] += 1 功能的逻辑或知识是否有缺陷?如果没有,defaultdict中的任何值如何设置为0?

编辑:我也非常确定脚本中没有其他部分会扭曲这些结果,因为我在显示代码后立即使用以下方法测试字典:

word_dd

3 个答案:

答案 0 :(得分:6)

当您访问defaultdict中的某个密钥时,如果该密钥不存在,则会自动创建该密钥。由于我们将int作为默认工厂函数,因此它会创建密钥并提供默认值0。

from collections import defaultdict
d = defaultdict(int)
print d["a"]
# 0
print d
# defaultdict(<type 'int'>, {'a': 0})

因此,在访问密钥之前,您应该确保它存在于defaultdict实例中,就像这样

print "a" in d
# False

答案 1 :(得分:6)

对密钥的任何项访问都将实现值:

>>> from collections import defaultdict
>>> d = defaultdict(int)
>>> d['foo']
0

使用包含来测试存在:

>>> 'bar' in d
False
>>> 'foo' in d
True

由于你在计算n-gram,你可能也想看看collections.Counter()

from collections import Counter

word_counter = Counter()
for letter_n_gram in word:
    word_counter.update(lexicon[n_gram])

Counter.update()将更新lexicon[n_gram]表达式返回的所有条目的计数。

defaultdict(int)一样,Counter()个对象自动实现值,默认为整数0

答案 2 :(得分:0)

唉,我在代码中发现了错误。

由于在我的输入集中有许多相同的单词n-gram和相同的测试单词,我只会根据唯一的测试单词创建类似单词的字典。

此词典随后用于其他目的,其中键被多次测试。当然,如果字典为collections.defaultdict且默认工厂未设置为None,则可以创建零值元素。

然而,在每个主循环中测试零值元素 - 因此找到在前一循环中创建的零值元素。

将测试代码缩进到适当的部分后,结果如预期的那样 - 创建后不会立即出现零值元素。

我想向所有人道歉,因为我的问题错误和不完整 - 其他人都无法找到错误。