2013-08-05 5 views
5

Когда я изменилв питона, почему, если ранг: быстрее, чем если ранг = 0:

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 

Я нашел второй код является гораздо более эффективным, почему?

скамейка отметьте его, и в моей ситуации ранги представляют собой целочисленный массив целых чисел. Разница намного больше.

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

как вы узнали, что? Вы сравнили это? – zsong

+0

Я бы ожидал немного повышения, так как меньше работы происходит в интерпретированном Python, и многое другое происходит во встроенных методах, но в реальной программе это, вероятно, не будет большим. (Это все равно стоит, так как это стандартный стиль и меньше кода.) – user2357112

ответ

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 

Разница в том, что, в то время как первый случай включает в себя сравнение с нулем, второй случай просто проверяет, является ли false.

Чтобы посмотреть, что он делает, используйте 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 
+0

Я, моя ситуация, ранги - целочисленный массив numpy. Похоже, что разница намного больше. – BerSerK

+0

Если вы 'dis' оба образца, разница по-прежнему' LOAD_CONST 1 (0) 'и' COMPARE_OP 3 (! =) '. – SheetJS

+0

, но как объяснить, замените ли это 'if' на' i == True'? последний еще медленнее – zsong

Смежные вопросы