una soporta segundo rapida por optimizar mas lentas lenta hacer cuello cuantas consultas consulta como botella agilizar python performance if-statement boolean timeit

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:

  1. De acuerdo con la respuesta del Sr. Sylvain Defresne en esta pregunta , todo se convierte implícitamente en un bool primero y luego se comprueba. Entonces, ¿por qué es if True más lento que if 1 ?
  2. ¿Por qué es test3 más lento que test1 aunque solo los valores de return son diferentes?
  3. Me gusta la pregunta 2, pero ¿por qué es test4 un poco más rápido que test2 ?

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.