python - soporta - ¿Por qué es más lento si es verdadero si 1?
optimizar consultas mysql explain (2)
¿Por qué es if True más lento que if 1 en Python? ¿No debería if True más rápido que if 1 ?
Estaba tratando de aprender el módulo timeit . A partir de lo básico, probé estos:
>>> 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
Estoy confundido por estas cosas:
- De acuerdo con la respuesta del Sr. Sylvain Defresne en esta pregunta , todo se convierte implícitamente en un
boolprimero y luego se comprueba. Entonces, ¿por qué esif Truemás lento queif 1? - ¿Por qué es
test3más lento quetest1aunque solo los valores dereturnson diferentes? - Me gusta la pregunta 2, pero ¿por qué es
test4un poco más rápido quetest2?
NOTA: Lo timeit tres veces y tomé el promedio de los resultados, luego publiqué los tiempos aquí junto con el código.
Esta pregunta no se relaciona con la forma de realizar un micro benchmarking (lo que hice en este ejemplo, pero también entiendo que es demasiado básico), pero la razón por la que verificar una variable "Verdadera" es más lenta que una constante.
Desmontaje bytecode hace la diferencia obvia.
>>> 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
Como mencionó Kabie, True y False son globales en Python 2. Muchas cosas van a tener acceso a ellos.
>>> dis.dis(test2)
3 0 LOAD_CONST 1 (1)
3 RETURN_VALUE
El compilador de Python pudo reconocer 1 como una expresión "veraz" constante y optimizar la condición redundante.
>>> 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
Más o menos lo mismo que test1 , con un LOAD_GLOBAL más.
>>> dis.dis(test4)
3 0 LOAD_GLOBAL 0 (True)
3 RETURN_VALUE
Ver test2 . Pero LOAD_GLOBAL es un poco más costoso que LOAD_CONST .
True y False no son palabras clave en Python 2 .
Deben resolverse en tiempo de ejecución. Esto ha sido cambiado en Python 3.
La misma prueba en 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
El error de tiempo es del 1%, lo cual es aceptable.