我最近发现并开始使用默认词典来替换几个更庞大的构造。我读过'蟒蛇的禅',蟒蛇的关键点之一就是“应该有一个 - 最好只有一个 - 明显的方式来做它。”
基于该标准(或者更实际地基于内存使用或速度),以下哪些(或完全不同的东西)最好?我有预感,第一个是正确的,但希望其他人的意见。
my_dict = defaultdict(int)
for generic in iterable:
my_dict[generic] +=1
或:
my_dict = {}
for generic in iterable:
if generic not in my_dict:
my_dict[generic] = 1
else:
my_dict[generic]+=1
或:
my_dict = {}
for generic in iterable:
try:
my_dict[generic] += 1
except(KeyError):
my_dict[generic] = 1
使用my_dict = defaultdict(list)和使用append函数也是如此。假设使用了多个for循环或其他条件,而不是简单地计算单个iterable中的泛型值,因为这显然会有不同的特性。
答案 0 :(得分:3)
如果你坚持使用字典或defaultdict,第一个是最好的。然而,为了计算,在集合中有一个名为Counter的可爱类:
>>> from collections import Counter
>>> c = Counter()
>>> for generic in iterable:
... c.update(generic)
甚至更短:
>>> c = Counter(iterable)
答案 1 :(得分:2)
正如Paulo Almeida评论的那样,对于您发布的“明显”解决方案的示例是使用collections.Counter
:
from collections import Counter
my_dict = Counter(iterable)
就是这样。
至于您发布的其他代码段,并假设my_dict[key] += 1
仅用于示例,而您的一般问题是“如何最好地填充字典”:collections.defaultdict
是同类的正确选择dicts(所有键的相同类型的值),其中类型具有默认值(数字零,空字符串,空列表...)。我能想到的最常见的用例是填充列表(或集合或其他容器)的字典。
现在当collections.Counter
和collections.defaultdict
都没有解决您的问题时,您有三种可能的模式:
dict.setdefault(key, value)
如果您希望密钥已经存在,则try / except解决方案会更快 - 尝试/除外块设置非常快,但在引发异常时成本很高。就我而言,我不推荐它,除非你非常非常确定你的数据现在是什么和它们将来会是什么样子
“先寻找”解决方案的成本几乎不变,虽然不是免费的,但仍然相当便宜。这真是你最安全的选择。
dict.setdefault()
解决方案的成本与“前一个”解决方案的成本大致相同,但是您也有不变的默认对象实例,通常会立即崩溃。几年前这是一种常见的模式,但是自collection.defaultdict
出现以来它的使用相当少,而不是说大多数都没用。