Why is if True slower than if 1?
True
and False
are not keywords in Python 2.
They must resolve at runtime. This has been changed in Python 3
Same test on 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
Time error is in 1%, which is acceptable.
Bytecode disassembly makes difference obvious.
>>> 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
As Kabie mentioned, True
and False
are globals in Python 2. Lots of stuff is going on to access them.
>>> dis.dis(test2) 3 0 LOAD_CONST 1 (1) 3 RETURN_VALUE
Python compiler was able to recognize 1
as a constantly "truthy" expression and optimize redundant condition away!
>>> 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
Pretty much the same as test1
, with one more LOAD_GLOBAL
.
>>> dis.dis(test4) 3 0 LOAD_GLOBAL 0 (True) 3 RETURN_VALUE
See test2
. But LOAD_GLOBAL
is a bit more costly than LOAD_CONST
.