dict.get()方法的效率

时间:2013-02-02 17:27:53

标签: python methods dictionary get

我刚刚开始学习python并担心如果我使用dict.get(key,default_value)或者我为它定义了自己的方法......那么它们有什么不同之处:

[第一种方法]:

dict={}
for c in string:
    if c in dict:
        dict[c]+=1
    else:
        dict[c]=1

和python提供的另一个dict.get()方法

for c in string:
    dict[c]=dict.get(c,0)+1

他们在效率或速度方面有任何差异......或者它们是相同的,第二个只能节省更多的代码行...

1 个答案:

答案 0 :(得分:6)

对于这种特定情况,请改为使用collections.Counter()collections.defaultdict()对象:

import collections

dct = collections.defaultdict(int)

for c in string:
     dict[c] += 1

dct = collections.Counter(string)

两者都是标准dict类型的子类。 Counter类型添加了一些更有用的功能,例如汇总两个计数器或列出已计数的最常见实体。 defaultdict类也可以被赋予其他默认类型;例如,使用defaultdict(list)将内容收集到每个键的列表中。

如果要比较两种不同方法的效果,您需要使用timeit module

>>> import timeit
>>> def intest(dct, values):
...     for c in values:
...         if c in dct:
...             dct[c]+=1
...         else:
...             dct[c]=1
... 
>>> def get(dct, values):
...     for c in values:
...         dct[c] = dct.get(c, 0) + 1
... 
>>> values = range(10) * 10
>>> timeit.timeit('test(dct, values)', 'from __main__ import values, intest as test; dct={}')
22.210275888442993
>>> timeit.timeit('test(dct, values)', 'from __main__ import values, get as test; dct={}')
27.442166090011597

这表明使用in的速度要快一些。

但是,有一个第三个​​选项需要考虑;抓住KeyError例外:

>>> def tryexcept(dct, values):
...     for c in values:
...         try:
...             dct[c] += 1
...         except KeyError:
...             dct[c] = 1
... 
>>> timeit.timeit('test(dct, values)', 'from __main__ import values, tryexcept as test; dct={}')
18.023509979248047

恰好是最快的,因为10个案例中只有1个用于新密钥。

最后但并非最不重要的是,我提出了两个备选方案:

>>> def default(dct, values):
...     for c in values:
...         dct[c] += 1
... 
>>> timeit.timeit('test(dct, values)', 'from __main__ import values, default as test; from collections import defaultdict; dct=defaultdict(int)')
15.277361154556274
>>> timeit.timeit('Counter(values)', 'from __main__ import values; from collections import Counter')
38.657804012298584

因此Counter()类型最慢,但defaultdict确实非常Counter()做了很多工作,而额外的功能可以使其他地方的开发和执行速度更快。