Python 就效率/快速拒绝问题而言,如果您的if语句在同一行上,这是否重要?

Python 就效率/快速拒绝问题而言,如果您的if语句在同一行上,这是否重要?,python,performance,processing-efficiency,Python,Performance,Processing Efficiency,例如,假设我想找到1到1000之间所有可以被3和5整除的数字。守则可否: for i in range(1,1000): if i % 3==0 and i %5 == 0: blah 不如说 for i in range(1,1000): if i%3==0: if i%5==0: blah 计算机是否检查这两种情况?例如,如果i=10。第一台计算机会同时计算i%3和i%5,还是会计算i%3然后中断?在这种情况下,将易于检

例如,假设我想找到1到1000之间所有可以被3和5整除的数字。守则可否:

for i in range(1,1000):
    if i % 3==0 and i %5 == 0:
        blah
不如说

for i in range(1,1000):
    if i%3==0:
       if i%5==0:
           blah

计算机是否检查这两种情况?例如,如果i=10。第一台计算机会同时计算i%3和i%5,还是会计算i%3然后中断?在这种情况下,将易于检查/拒绝的条件放在左侧会更有效,对吗?

否,一旦其中一个条件为false,它将返回false。这叫做短路。请参阅。

在python和许多语言中,布尔表达式都有一个完整的定义。这意味着一旦我们确定布尔表达式的真值,计算就会停止。在这方面,两个代码片段是等效的

但是,您可以通过更改顺序进行优化。例如,最好使用:

if i % 5 == 0 and i % 3 == 0
原因是一个数字很少是5的倍数,所以在大多数情况下,这个表达式会更早失败


例如,如果我们检查从1到150的数字,检查
i%5==0
将失败120个数字。因此,我们将对
i%5==0
执行120次检查,对
i%5==0
i%3==0
执行30次检查。这总共是180张支票。类似地,对于
如果i%3==0和i%5==0,我们将执行
100+2*50=200
检查。

除了解释
短路的其他答案之外,这两个答案都做一项工作,性能之间没有太大差异

请参见以下基准:

s1="""
for i in range(1,1000):
    if i % 3==0 and i %5 == 0:
        pass
"""
s2="""
for i in range(1,1000):
    if i%3==0:
       if i%5==0:
           pass

    """


print ' first: ' ,timeit(stmt=s1, number=1000)
print 'second : ',timeit(stmt=s2, number=1000) 
结果:

 first:  0.0738339424133
second :  0.0790829658508
正如您所看到的,差异是
0.006
,这是因为第二部分中有一个额外的块加载

您还可以使用
dis
模块来分解python字节码:

使用
的第一个循环:

 21           0 SETUP_LOOP              58 (to 61)
              3 LOAD_GLOBAL              0 (range)
              6 LOAD_CONST               1 (1)
              9 LOAD_CONST               2 (1000)
             12 CALL_FUNCTION            2
             15 GET_ITER            
        >>   16 FOR_ITER                41 (to 60)
             19 STORE_FAST               0 (i)

 22          22 LOAD_FAST                0 (i)
             25 LOAD_CONST               3 (3)
             28 BINARY_MODULO       
             29 LOAD_CONST               4 (0)
             32 COMPARE_OP               2 (==)
             35 POP_JUMP_IF_FALSE       16
             38 LOAD_FAST                0 (i)
             41 LOAD_CONST               5 (5)
             44 BINARY_MODULO       
             45 LOAD_CONST               4 (0)
             48 COMPARE_OP               2 (==)
             51 POP_JUMP_IF_FALSE       16

 23          54 JUMP_ABSOLUTE           16
             57 JUMP_ABSOLUTE           16
        >>   60 POP_BLOCK           
        >>   61 LOAD_CONST               0 (None)
             64 RETURN_VALUE 
第二点:

26           0 SETUP_LOOP              61 (to 64)
              3 LOAD_GLOBAL              0 (range)
              6 LOAD_CONST               1 (1)
              9 LOAD_CONST               2 (1000)
             12 CALL_FUNCTION            2
             15 GET_ITER            
        >>   16 FOR_ITER                44 (to 63)
             19 STORE_FAST               0 (i)

 27          22 LOAD_FAST                0 (i)
             25 LOAD_CONST               3 (3)
             28 BINARY_MODULO       
             29 LOAD_CONST               4 (0)
             32 COMPARE_OP               2 (==)
             35 POP_JUMP_IF_FALSE       16

 28          38 LOAD_FAST                0 (i)
             41 LOAD_CONST               5 (5)
             44 BINARY_MODULO       
             45 LOAD_CONST               4 (0)
             48 COMPARE_OP               2 (==)
             51 POP_JUMP_IF_FALSE       60

 29          54 JUMP_ABSOLUTE           60
             57 JUMP_ABSOLUTE           16
        >>   60 JUMP_ABSOLUTE           16
        >>   63 POP_BLOCK           
        >>   64 LOAD_CONST               0 (None)
             67 RETURN_VALUE  

我还学到了一个新短语,短路,谢谢@jornsharpeoh,很简单。每种语言都是一样的吗?我不确定“每种”语言,但这里列出了一些@avid19某些语言需要不同语法的语言-例如在VB.NET中,基本
不短路,而是
执行。这就是我的想法,快速拒绝总是更好的。谢谢-1,这两个表达式的组合是相同的。时间上的任何差异都是由于测试环境的差异和不可靠性造成的。@NickBastin我认为这表明,他们说“性能之间没有太大差异”。@NickBastin正如avid19所说,我没有说没有任何差异!检查编辑!