5

当我改变

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

我发现第二个代码效率更高,为什么?

基准它,在我的情况下,ranks 是一个 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
4

1 回答 1

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
于 2013-08-05T03:11:11.960 回答