[英]defaultdict vs dict element initialization
我正在尝试优化脚本的性能,该脚本在给出的每个单词的词典中查找相似的单词。
每个唯一的单词将被分成字母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
这个实现可以工作,但是通过切换collections.defaultdict
的dict
可以更快地运行脚本。
word_dd = defaultdict(int)
for letter_n_gram in word:
for entry in lexicon[n_gram]:
word_dd[entry] += 1
没有其他代码被更改。
我的印象是两个代码片段(最重要的是分数添加)应该以完全相同的方式工作,即如果密钥存在,将其值增加1,如果它不存在,则创建密钥并将值设置为1。
但是,在运行新代码之后,某些键的值为0,我觉得这在逻辑上是不可能的。
我对defaultdict
功能的逻辑或知识是否有缺陷? 如果没有, word_dd
任何值如何设置为0?
编辑:我也非常确定脚本中没有其他部分会扭曲这些结果,因为我使用以下代码在显示代码后立即测试字典:
for item in word_dd.iteritems():
if item[1] == 0:
print "Found zero value element"
break
当您访问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
对密钥的任何项访问都将实现该值:
>>> 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
。
唉,我在代码中发现了错误。
由于在我的输入集中有许多随后的单词n-gram和相同的测试单词,我只是每个唯一的测试单词创建一个相似单词的字典。
然后,该字典用于其他目的,其中密钥被多次测试。 当然,如果字典是collections.defaultdict
并且默认工厂未设置为None
,则可以创建零值元素。
然而,在每个主循环中进行零值元素的测试 - 因此找到在前一循环中创建的零值元素。
在将测试代码缩进到适当的部分之后,结果如预期的那样 - 在创建之后不会立即出现零值元素。
我想向所有人道歉,因为我的问题错误和不完整 - 其他人都无法找到错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.