Intrigado por esta pregunta sobre bucles infinitos en perl: while (1) Vs. para (;;) ¿Hay una diferencia de velocidad? , Decidí ejecutar una comparación similar en Python. Esperaba que el compilador generara el mismo código de bytes para while(True): passy while(1): pass, pero este no es el caso en python2.7.
El siguiente guión:
import dis
def while_one():
while 1:
pass
def while_true():
while True:
pass
print("while 1")
print("----------------------------")
dis.dis(while_one)
print("while True")
print("----------------------------")
dis.dis(while_true)
produce los siguientes resultados:
while 1
----------------------------
4 0 SETUP_LOOP 3 (to 6)
5 >> 3 JUMP_ABSOLUTE 3
>> 6 LOAD_CONST 0 (None)
9 RETURN_VALUE
while True
----------------------------
8 0 SETUP_LOOP 12 (to 15)
>> 3 LOAD_GLOBAL 0 (True)
6 JUMP_IF_FALSE 4 (to 13)
9 POP_TOP
9 10 JUMP_ABSOLUTE 3
>> 13 POP_TOP
14 POP_BLOCK
>> 15 LOAD_CONST 0 (None)
18 RETURN_VALUE
Usar while Truees notablemente más complicado. ¿Por qué es esto?
En otros contextos, Python actúa como si fuera Trueigual a 1:
>>> True == 1
True
>>> True + True
2
¿Por qué whiledistingue a los dos?
Noté que python3 evalúa las declaraciones utilizando operaciones idénticas:
while 1
----------------------------
4 0 SETUP_LOOP 3 (to 6)
5 >> 3 JUMP_ABSOLUTE 3
>> 6 LOAD_CONST 0 (None)
9 RETURN_VALUE
while True
----------------------------
8 0 SETUP_LOOP 3 (to 6)
9 >> 3 JUMP_ABSOLUTE 3
>> 6 LOAD_CONST 0 (None)
9 RETURN_VALUE
¿Hay un cambio en python3 en la forma en que se evalúan los booleanos?

Respuestas:
En Python 2.x,
Trueno es una palabra clave, sino solo una constante global incorporada que se define como 1 en elbooltipo. Por lo tanto, el intérprete todavía tiene que cargar el contenido deTrue. En otras palabras,Truees reasignable:En Python 3.x realmente se convierte en una palabra clave y una constante real:
así, el intérprete puede reemplazar el
while True:bucle con un bucle infinito.fuente
while 1ywhile Trueson idénticos en Python 3?Esto no está del todo bien
ya que uno todavía puede salir del bucle. Pero es cierto que
elsenunca se accedería a dicha cláusula de bucle en Python 3. Y también es cierto que simplificar la búsqueda de valores hace que se ejecute tan rápido comowhile 1en Python 2.Comparación de rendimiento
Demostrando la diferencia en el tiempo para un bucle while algo no trivial:
Preparar
Python 2
Python 3
Explicación
Para explicar la diferencia, en Python 2:
pero en Python 3:
Dado que
Truees una palabra clave en Python 3, el intérprete no tiene que buscar el valor para ver si alguien lo reemplazó con algún otro valor. Pero como se puede asignarTruea otro valor, el intérprete tiene que buscarlo cada vez.Conclusión para Python 2
Si tiene un bucle estrecho y de larga duración en Python 2, probablemente debería usar en
while 1:lugar dewhile True:.Conclusión para Python 3
Úselo
while True:si no tiene ninguna condición para salir de su bucle.fuente
Esta es una pregunta de 7 años que ya tiene una gran respuesta, pero un concepto erróneo en la pregunta, que no se aborda en ninguna de las respuestas, hace que sea potencialmente confuso para algunas de las otras preguntas marcadas como duplicadas.
De hecho,
whileno está haciendo nada diferente aquí. Se distingue1yTrueexactamente de la misma manera que lo hace el+ejemplo.Aquí está 2.7:
Ahora compare:
Emite un
LOAD_GLOBAL (True)para cada unoTrue, y el optimizador no puede hacer nada con un global. Entonces, sewhiledistingue1yTrueexactamente por la misma razón que lo+hace. (Y==no los distingue porque el optimizador no optimiza las comparaciones).Ahora compare 3.6:
Aquí, emite una
LOAD_CONST (True)para la palabra clave, que el optimizador puede aprovechar. Entonces,True + 1no distingue, exactamente por la misma razónwhile Trueque no lo hace. (Y==todavía no los distingue porque el optimizador no optimiza las comparaciones).Mientras tanto, si el código no está optimizado a cabo, el intérprete termina el tratamiento
Truey1exactamente el mismo en los tres de estos casos.booles una subclase deint, hereda la mayoría de sus métodosintyTruetiene un valor entero interno de 1. Entonces, ya sea que esté haciendo unawhileprueba (__bool__en 3.x,__nonzero__en 2.x), una comparación (__eq__) o aritmética (__add__), está llamando al mismo método ya sea que useTrueo1.fuente