我只是好奇而已。例如,如果我想檢查是否一個數是偶數,任何一項都將工作:Python是否在運行時自動優化(在某種程度上)?
# values are True if even, False if odd
even_masked = not (number & 0x1)
even_modulo = (number%2 == 0)
他們都做同樣的事情,但第一種方法是更快的時鐘週期計算。在C中,你可以設置編譯器爲你做這樣的優化,但是Python解釋器是否做了類似的事情?
我只是好奇而已。例如,如果我想檢查是否一個數是偶數,任何一項都將工作:Python是否在運行時自動優化(在某種程度上)?
# values are True if even, False if odd
even_masked = not (number & 0x1)
even_modulo = (number%2 == 0)
他們都做同樣的事情,但第一種方法是更快的時鐘週期計算。在C中,你可以設置編譯器爲你做這樣的優化,但是Python解釋器是否做了類似的事情?
的這兩個函數的字節碼是不同的,這要歸功於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
因此,請保持腳本可讀,而不要進行這種優化。你會了解第一線鬆動時間會方式比保存在執行的時候更重要的是,即使是使用腳本萬次:-)
的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
我你看起來很符合你的表達。
Python的字節碼解釋器的開銷使得模數的成本變得不足,包括獲得'number'的值所需的指針間接尋址,對它的類型檢查以及refcounting :) –