在python中为什么如果排名:比排名更快!= 0:

时间:2013-08-05 02:45:11

标签: python performance numpy

当我改变时

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

为:

for i in range(0, 100):
    rank = ranks[i]
    if rank:
        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

1 个答案:

答案 0 :(得分:8)

将支票提炼到核心

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

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

不同之处在于,虽然第一种情况涉及比较为零,但第二种情况只是测试是否为假。

要了解它的作用,请使用dis

>>> 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