Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么三元运算符的运算速度更快呢?_Python_Python 2.7_Dictionary - Fatal编程技术网

Python 为什么三元运算符的运算速度更快呢?

Python 为什么三元运算符的运算速度更快呢?,python,python-2.7,dictionary,Python,Python 2.7,Dictionary,我最近发现了一些令人惊讶的事情。给定不包含键k的dictd,使用三元运算符尝试检索具有默认返回值的项: >>> def tern(): ... d[k] if k in d else 'foo' ... >>> timeit.timeit(tern, number=1000000) 0.12342095375061035 运行速度比dict的快。get()函数: >>> def get_meth(): ... d.get(k

我最近发现了一些令人惊讶的事情。给定不包含键
k
的dict
d
,使用三元运算符尝试检索具有默认返回值的项:

>>> def tern():
...     d[k] if k in d else 'foo'
...
>>> timeit.timeit(tern, number=1000000)
0.12342095375061035
运行速度比dict的
快。get()
函数:

>>> def get_meth():
...     d.get(k, 'foo')
...
>>> timeit.timeit(get_meth, number=1000000)
0.20549297332763672
这对我来说似乎是违反直觉的。我认为三元运算符需要在dict中进行两次搜索(一次是在d中测试
k),然后另一次是检索
d[k]
,而
.get
只需尝试检索
d[k]
,如果失败,则返回
'foo'


我在一个大的dict(一百万个元素)和一个小的dict(100个元素)上运行了这个,这两次,三元的速度都明显更快。这里的幕后发生了什么?

如果你分解这两个方法,你会看到
get
有一个额外的
CALL\u函数
,这在python中比
POP\u JUMP\u If\u FALSE
指令更昂贵

如果处于

  3           0 LOAD_CONST               1 ('blub')
              3 LOAD_GLOBAL              0 (d)
              6 COMPARE_OP               6 (in)
              9 POP_JUMP_IF_FALSE       22
             12 LOAD_GLOBAL              0 (d)
             15 LOAD_CONST               1 ('blub')
             18 BINARY_SUBSCR       
             19 JUMP_FORWARD             3 (to 25)
        >>   22 LOAD_CONST               2 ('foo')
        >>   25 POP_TOP             
             26 LOAD_CONST               0 (None)
             29 RETURN_VALUE        
获取方法:

  6           0 LOAD_GLOBAL              0 (d)
              3 LOAD_ATTR                1 (get)
              6 LOAD_CONST               1 ('blub')
              9 LOAD_CONST               2 ('foo')
             12 CALL_FUNCTION            2          #Expensive call
             15 POP_TOP             
             16 LOAD_CONST               0 (None)
             19 RETURN_VALUE        
我不久前读过一篇很长的文章,其中有一节描述了
CALL\u函数
如此昂贵的原因:

您多久点击一次
else
?“给定一个不包含键
k
的dict
d
”,因此每次给定该键在测试中从不在dict中,三元表达式的
d[k]
部分都不会执行。因此,在任何一种情况下都只进行一次查找。剩下的是在
d.get()
中有另一个dict查找:必须在包含
d
方法的dict中查找属性“get”。设置
m=d.get
并将函数体更改为
m(k,'foo')
,您将看到一个很大的不同,k,有趣的结果:如果对象的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>不是用C实现的(我猜dict是?),那么设置
和运行时?