简体   繁体   English

为什么内联if / else比Python中的.get()快?

[英]Why is an inline if/else faster than a .get() in Python?

I was reviewing some code earlier and the developer wrote an inline if / else rather than a get() to retrieve an element from a list if it exists (otherwise give it a default value). 我早些时候在回顾一些代码,开发人员编写了一个内联if / else而不是get()来从列表中检索元素(如果存在)(否则为其提供默认值)。 I decided to spring some timeit code on repl and was pretty confused by the result. 我决定在repl上添加一些timeit代码,并对结果感到困惑。 The if / else takes 1/3 the time of the get() . if / else需要get()时间的1/3。

Here is the repl code , and below is the code in the repl as well as the result for posterity: 这是repl代码 ,下面是repl中的代码以及后代的结果:

import timeit

D = {"a": 1, "b": 2, "c": 3}

def ef(): return D['a'] if 'a' in D else 1

def gt(): return D.get('a', 1)

print "gt1", timeit.timeit(gt, number=10000)
print "ef1", timeit.timeit(ef, number=10000)
print "ef2", timeit.timeit(ef, number=10000)
print "gt2", timeit.timeit(gt, number=10000)

and the results: 结果:

gt1 0.0659999847412
ef1 0.0239999294281
ef2 0.0249998569489
gt2 0.0539999008179

and a visual of 10 iterations of the above timeit calls, where the result has been multiplied by 10000 for representation purposes 以及上述timeit调用的10次迭代的可视化结果,其中出于表示目的将结果乘以10000

10次​​迭代的视觉效果

The D.get() path includes an attribute lookup, and a method call: D.get()路径包括属性查找和方法调用:

>>> import dis
>>> D = {"a": 1, "b": 2, "c": 3}
>>> def gt(): return D.get('a', 1)
... 
>>> dis.dis(gt)
  1           0 LOAD_GLOBAL              0 (D)
              3 LOAD_ATTR                1 (get)
              6 LOAD_CONST               1 ('a')
              9 LOAD_CONST               2 (1)
             12 CALL_FUNCTION            2
             15 RETURN_VALUE        

The attribute lookup ( LOAD_ATTR ) especially slows things down. 属性查找( LOAD_ATTR )尤其会减慢速度。

If you remove the attribute lookup (and give the in test a local to work with), the field is evened out: 如果删除属性查找(并为in test提供一个可以使用的局部变量),则该字段将被平整:

>>> def gt_fast(D_get=D.get): return D_get('a', 1)
... 
>>> def ef_fast(D=D): return D['a'] if 'a' in D else 1
... 
>>> timeit.timeit(gt_fast)
0.2174091339111328
>>> timeit.timeit(ef_fast)
0.2139298915863037

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM