在python中,为什么if-rank:比if-rank快!=0:

在python中,为什么if-rank:比if-rank快!=0:,python,performance,numpy,Python,Performance,Numpy,当我改变 for i in range(0, 100): rank = ranks[i] if rank != 0: pass 致: 我发现第二个代码更有效,为什么 基准点,在我的情况下,秩是一个整数的numpy数组。差别要大得多 import numpy as np import time N = 1000000 ranks = np.random.random_integers(0, 10, N) start = time.time() for i in r

当我改变

for i in range(0, 100):
    rank = ranks[i]
    if rank != 0:
        pass
致:

我发现第二个代码更有效,为什么

基准点,在我的情况下,秩是一个整数的numpy数组。差别要大得多

import numpy as np
import time
N = 1000000
ranks = np.random.random_integers(0, 10, N)
start = time.time()
for i in range(0, N):
    rank = ranks[i]
    if rank != 0:
        pass

print time.time() - start
start = time.time()
for i in range(0, N):
    rank = ranks[i]
    if rank:
        pass
print time.time() - start
start = time.time()
for i in range(0, N):
    if i != 0:
        pass

print time.time() - start
start = time.time()
for i in range(0, N):
    if i:
        pass
print time.time() - start
输出:

1.15917396545
0.45020198822
0.123136997223
0.122531175613

将支票提取到核心

for i in range(0,100):
  if i != 0:
    pass

我们看到了不同

$ python -m timeit 'for i in range(0,100):' ' if i != 0:' '  pass'
100000 loops, best of 3: 4.69 usec per loop
$ python -m timeit 'for i in range(0,100):' ' if i:' '  pass'
100000 loops, best of 3: 4.18 usec per loop
不同之处在于,第一种情况涉及比较零,第二种情况只是测试是否为假

要查看它正在做什么,请使用:

>>def():
...  对于范围(0100)内的i:
...    如果我:
...      通过
...
>>>def g():
...  对于范围(0100)内的i:
...    如果我0:
...      通过
...
>>>从dis导入dis
>>>dis(f)
2 0设置环路32(至35)
3加载\u全局0(范围)
6负载常数1(0)
9荷载常数2(100)
12调用函数2
15获得
>>国际热核聚变实验堆15(至34)16
19商店快速0(i)
3 22加载速度0(i)
25如果为假,则弹出跳转16
4 28跳跃式绝对16
31绝对值16
>>34波普卢大厦
>>35负载常数0(无)
38返回值
>>>dis(g)
2 0设置环路38(至41)
3加载\u全局0(范围)
6负载常数1(0)
9荷载常数2(100)
12调用函数2
15获得
>>国际热核聚变实验堆21(至40)16
19商店快速0(i)
3 22加载速度0(i)
25负载常数1(0)40 POP_块
>>41负载常数0(无)
44返回值

你是怎么发现的?你做过基准测试吗?我希望有一点提升,因为在解释型Python中进行的工作较少,而在内置方法中进行的工作较多,但在实际程序中,这可能不会很大。(这仍然值得一做,因为它是标准样式,代码更少。)在我的情况下,秩是一个整数数组numpy。差异似乎更大。如果您
dis
这两个示例,差异仍然是
LOAD_CONST 1(0)
COMPARE_OP 3(!=)
。但是,如果将
If
替换为
i==True
,如何解释?后者更为公平slower@sza很简单,
True
是全局的,因此python执行操作
LOAD\u global
,而不是Py2k中的
LOAD\u CONST
,您可以执行
True,False=False,True
,这使得
False==not True
,但是
False
现在是
True
True
现在是
False
for i in range(0,100):
  if i:
    pass
$ python -m timeit 'for i in range(0,100):' ' if i != 0:' '  pass'
100000 loops, best of 3: 4.69 usec per loop
$ python -m timeit 'for i in range(0,100):' ' if i:' '  pass'
100000 loops, best of 3: 4.18 usec per loop
>>> def f():
...  for i in range(0,100):
...    if i:
...      pass
...
>>> def g():
...  for i in range(0,100):
...    if i != 0:
...      pass
...
>>> from dis import dis
>>> dis(f)
  2           0 SETUP_LOOP              32 (to 35)
              3 LOAD_GLOBAL              0 (range)
              6 LOAD_CONST               1 (0)
              9 LOAD_CONST               2 (100)
             12 CALL_FUNCTION            2
             15 GET_ITER
        >>   16 FOR_ITER                15 (to 34)
             19 STORE_FAST               0 (i)

  3          22 LOAD_FAST                0 (i)
             25 POP_JUMP_IF_FALSE       16

  4          28 JUMP_ABSOLUTE           16
             31 JUMP_ABSOLUTE           16
        >>   34 POP_BLOCK
        >>   35 LOAD_CONST               0 (None)
             38 RETURN_VALUE
>>> dis(g)
  2           0 SETUP_LOOP              38 (to 41)
              3 LOAD_GLOBAL              0 (range)
              6 LOAD_CONST               1 (0)
              9 LOAD_CONST               2 (100)
             12 CALL_FUNCTION            2
             15 GET_ITER
        >>   16 FOR_ITER                21 (to 40)
             19 STORE_FAST               0 (i)

  3          22 LOAD_FAST                0 (i)
             25 LOAD_CONST               1 (0)   <-- this only happens in != 0
             28 COMPARE_OP               3 (!=)  <-- this only happens in != 0
             31 POP_JUMP_IF_FALSE       16

  4          34 JUMP_ABSOLUTE           16
             37 JUMP_ABSOLUTE           16
        >>   40 POP_BLOCK
        >>   41 LOAD_CONST               0 (None)
             44 RETURN_VALUE