Pythonでif True
がif 1
より遅いのはなぜですか? if True
はif 1
よりも速くすべきではありませんか?
私はtimeit
モジュールを学ぼうとしていました。基本から始めて、私はこれらを試しました:
>>> def test1():
... if True:
... return 1
... else:
... return 0
>>> print timeit("test1()", setup = "from __main__ import test1")
0.193144083023
>>> def test2():
... if 1:
... return 1
... else:
... return 0
>>> print timeit("test2()", setup = "from __main__ import test2")
0.162086009979
>>> def test3():
... if True:
... return True
... else:
... return False
>>> print timeit("test3()", setup = "from __main__ import test3")
0.214574098587
>>> def test4():
... if 1:
... return True
... else:
... return False
>>> print timeit("test4()", setup = "from __main__ import test4")
0.160849094391
私はこれらのことに混乱しています:
bool
に変換され、次にチェックされます。では、なぜif True
はif 1
よりも遅いのでしょうか。return
の値だけが異なるのに、test3
がtest1
より遅いのはなぜですか?test4
がtest2
よりも少し速いのはなぜですか?注:私はtimeit
を3回実行し、結果の平均を取り、コードとともにここに時間を投稿しました。
この質問は、マイクロベンチマークの実行方法(この例では実行しましたが、基本的すぎることも理解しています)とは関係ありませんが、「True」変数のチェックが定数よりも遅いのはなぜですか。
True
とFalse
は Python 2 のキーワードではありません。
それらは実行時に解決する必要があります。これは Python で変更されました
Python 3:で同じテスト
>>> timeit.timeit('test1()',setup="from __main__ import test1", number=10000000)
2.806439919999889
>>> timeit.timeit('test2()',setup="from __main__ import test2", number=10000000)
2.801301520000038
>>> timeit.timeit('test3()',setup="from __main__ import test3", number=10000000)
2.7952816800000164
>>> timeit.timeit('test4()',setup="from __main__ import test4", number=10000000)
2.7862537199999906
時間誤差は1%であり、これは許容範囲です。
バイトコードの逆アセンブルは違いを明らかにします。
>>> dis.dis(test1)
2 0 LOAD_GLOBAL 0 (True)
3 JUMP_IF_FALSE 5 (to 11)
6 POP_TOP
3 7 LOAD_CONST 1 (1)
10 RETURN_VALUE
>> 11 POP_TOP
5 12 LOAD_CONST 2 (0)
15 RETURN_VALUE
16 LOAD_CONST 0 (None)
19 RETURN_VALUE
Kabieが述べたように、True
とFalse
はPython 2。のグローバルです。それらにアクセスするために多くのものが進行中です。
>>> dis.dis(test2)
3 0 LOAD_CONST 1 (1)
3 RETURN_VALUE
Pythonコンパイラは、1
を常に「真実の」式として認識し、冗長な状態を最適化することができました。
>>> dis.dis(test3)
2 0 LOAD_GLOBAL 0 (True)
3 JUMP_IF_FALSE 5 (to 11)
6 POP_TOP
3 7 LOAD_GLOBAL 0 (True)
10 RETURN_VALUE
>> 11 POP_TOP
5 12 LOAD_GLOBAL 1 (False)
15 RETURN_VALUE
16 LOAD_CONST 0 (None)
19 RETURN_VALUE
test1
とほぼ同じですが、もう1つLOAD_GLOBAL
があります。
>>> dis.dis(test4)
3 0 LOAD_GLOBAL 0 (True)
3 RETURN_VALUE
test2
を参照してください。ただし、LOAD_GLOBAL
はLOAD_CONST
よりも少しコストがかかります。