[英]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
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.