2014-01-23 49 views
0

我只是好奇而已。例如,如果我想檢查是否一個數是偶數,任何一項都將工作:Python是否在運行時自動優化(在某種程度上)?

# values are True if even, False if odd
even_masked = not (number & 0x1)
even_modulo = (number%2 == 0)

他們都做同樣的事情,但第一種方法是更快的時鐘週期計算。在C中,你可以設置編譯器爲你做這樣的優化,但是Python解釋器是否做了類似的事情?

+0

Python的字節碼解釋器的開銷使得模數的成本變得不足,包括獲得'number'的值所需的指針間接尋址,對它的類型檢查以及refcounting :) –

回答

0

的這兩個函數的字節碼是不同的,這要歸功於dis模塊:

>>> def test(number): 
...  even_masked = not (number & 0x1) 
... 
>>> def test2(number): 
...  even_modulo = (number%2 == 0) 
... 
>>> dis.dis(test) 
    2   0 LOAD_FAST    0 (number) 
       3 LOAD_CONST    1 (1) 
       6 BINARY_AND 
       7 UNARY_NOT 
       8 STORE_FAST    1 (even_masked) 
      11 LOAD_CONST    0 (None) 
      14 RETURN_VALUE 
>>> dis.dis(test2) 
    2   0 LOAD_FAST    0 (number) 
       3 LOAD_CONST    1 (2) 
       6 BINARY_MODULO 
       7 LOAD_CONST    2 (0) 
      10 COMPARE_OP    2 (==) 
      13 STORE_FAST    1 (even_modulo) 
      16 LOAD_CONST    0 (None) 
      19 RETURN_VALUE 

但是...我們可以看到,有兩種方法之間的非常少的區別:

>>> timeit.timeit("even_modulo = (number%2 == 0)", setup="number=1", number=100000000) 
11.886679887771606 
>>> timeit.timeit("even_masked = not (number & 0x1)", setup="number=1", number=100000000) 
11.225641965866089 

因此,請保持腳本可讀,而不要進行這種優化。你會了解第一線鬆動時間會方式比保存在執行的時候更重要的是,即使是使用腳本萬次:-)

0

dis模塊顯示Python的引擎蓋下做的說明

對於not (number & 0x1)

  0 LOAD_GLOBAL    0 (number) 
      3 LOAD_CONST    1 (1) 
      6 BINARY_AND 
      7 UNARY_NOT 
      8 POP_TOP 

對於(number%2 == 0)

  0 LOAD_GLOBAL    0 (number) 
      3 LOAD_CONST    1 (2) 
      6 BINARY_MODULO 
      7 LOAD_CONST    2 (0) 
     10 COMPARE_OP    2 (==) 
     13 POP_TOP 

我你看起來很符合你的表達。

相關問題