1

我刚开始学习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

它们在效率或速度上是否有任何差异......或者它们是相同的,第二个只是节省了编写更多代码行......

4

1 回答 1

6

对于这种特定情况,请使用 acollections.Counter()collections.defaultdict()object 代替:

import collections

dct = collections.defaultdict(int)

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

或者

dct = collections.Counter(string)

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

当您想比较两种不同方法的性能时,您需要使用timeit模块

>>> 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()虽然 s 做了更多的工作,而且额外的功能可以在其他地方带来易于开发和执行速度的好处。

于 2013-02-02T17:30:21.870 回答