你问哪个更有效率。假设您正在谈论执行速度:如果您的数据很小,那没关系。如果它是大而典型的,“已经存在”的情况将比“不在字典中”的情况发生得更频繁。这一观察解释了一些结果。
下面是一些代码,可与timeit
模块一起使用以探索速度而无需文件读取开销。我冒昧地添加了第 5 种方法,该方法并非没有竞争力,并且可以在至少 1.5.2 [测试] 之后的任何 Python 上运行。
from collections import defaultdict, Counter
def tally0(iterable):
# DOESN'T WORK -- common base case for timing
d = {}
for item in iterable:
d[item] = 1
return d
def tally1(iterable):
d = {}
for item in iterable:
if item in d:
d[item] += 1
else:
d[item] = 1
return d
def tally2(iterable):
d = {}
for item in iterable:
try:
d[item] += 1
except KeyError:
d[item] = 1
return d
def tally3(iterable):
d = defaultdict(int)
for item in iterable:
d[item] += 1
def tally4(iterable):
d = Counter()
for item in iterable:
d[item] += 1
def tally5(iterable):
d = {}
dg = d.get
for item in iterable:
d[item] = dg(item, 0) + 1
return d
典型运行(在 Windows XP“命令提示符”窗口中):
prompt>\python27\python -mtimeit -s"t=1000*'now is the winter of our discontent made glorious summer by this son of york';import tally_bench as tb" "tb.tally1(t)"
10 loops, best of 3: 29.5 msec per loop
以下是结果(每循环毫秒):
0 base case 13.6
1 if k in d 29.5
2 try/except 26.1
3 defaultdict 23.4
4 Counter 79.4
5 d.get(k, 0) 29.2
另一个计时试验:
prompt>\python27\python -mtimeit -s"from collections import defaultdict;d=defaultdict(int)" "d[1]+=1"
1000000 loops, best of 3: 0.309 usec per loop
prompt>\python27\python -mtimeit -s"from collections import Counter;d=Counter()" "d[1]+=1"
1000000 loops, best of 3: 1.02 usec per loop
的速度Counter
可能是由于它部分在 Python 代码中实现,而defaultdict
完全在 C 中(至少在 2.7 中)。
请注意,这Counter()
不仅仅是“语法糖” defaultdict(int)
——它实现了一个完整的bag
akamultiset
对象——有关详细信息,请参阅文档;如果您需要一些花哨的后期处理,它们可能会让您免于重新发明轮子。如果您只想计算事物,请使用defaultdict
.
针对@Steven Rumbalski 提出的问题进行更新:“””我很好奇,如果将可迭代对象移至 Counter 构造函数中会发生什么情况:d = Counter(iterable)?(我有 python 2.6,无法对其进行测试。)“ “”
tally6:刚刚完成d = Count(iterable); return d
,需要 60.0毫秒
您可以查看源代码(SVN 存储库中的collections.py)......这是我Python27\Lib\collections.py
在iterable
不是映射实例时所做的事情:
self_get = self.get
for elem in iterable:
self[elem] = self_get(elem, 0) + 1
以前在任何地方看过该代码吗?只是为了调用可在 Python 1.5.2 中运行的代码,需要执行大量操作:-O