【问题标题】:Efficiency of dict.get() methoddict.get() 方法的效率
【发布时间】:2013-01-17 20:07:05
【问题描述】:

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

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

【问题讨论】:

  • 对于键计数,请改用collections.Counter对象..
  • 你也可以在这里使用collections.defaultdict(int)

标签: python methods dictionary get


【解决方案1】:

对于这种特定情况,请改用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

这恰好是最快的,因为只有十分之一的案例用于新密钥。

最后但同样重要的是,我提出了两种选择:

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

【讨论】:

  • 非常棒的功能它偏离了方向......但同样的问题......如果它只节省很少/很多编码,或者它在其他方面也更有效?如果是,那么其他哪些领域效率更高?
  • @user1977504:使用timeit 模块自行测试。 :-)
猜你喜欢
  • 2013-08-22
  • 1970-01-01
  • 2011-11-01
  • 1970-01-01
  • 2017-04-09
  • 2015-08-09
  • 1970-01-01
  • 1970-01-01
  • 2016-01-20
相关资源
最近更新 更多