我刚刚开始学习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
他们在效率或速度方面有任何差异......或者它们是相同的,第二个只能节省更多的代码行...
答案 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()
做了很多工作,而额外的功能可以使其他地方的开发和执行速度更快。