ur_dir proyectos handling ejemplos python

python - proyectos - mientras(1) vs. por cierto(Verdadero)-¿Por qué hay una diferencia?



keyerror ur_dir (3)

Intrigado por esta pregunta sobre bucles infinitos en perl: mientras (1) vs. para (;;) ¿Hay una diferencia de velocidad? , Decidí ejecutar una comparación similar en Python. Esperaba que el compilador generaría el mismo código de bytes para while(True): pass y while(1): pass , pero este no es el caso en python2.7.

El siguiente script:

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 True es notablemente más complicado. ¿Por qué es esto?

En otros contextos, Python actúa como si True es igual a 1:

>>> True == 1 True >>> True + True 2

¿Por qué while distingue a los dos?

Noté que python3 no evalúa las declaraciones usando 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 algún cambio en python3 en la forma en que se evalúan los booleanos?


En Python 2.x, True no es una palabra clave, sino solo una constante global incorporada que se define a 1 en el tipo bool . Por lo tanto, el intérprete todavía tiene que cargar los contenidos de True . En otras palabras, True es reasignable:

Python 2.7 (r27:82508, Jul 3 2010, 21:12:11) [GCC 4.0.1 (Apple Inc. build 5493)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> True = 4 >>> True 4

En Python 3.x realmente se convierte en una palabra clave y una constante real:

Python 3.1.2 (r312:79147, Jul 19 2010, 21:03:37) [GCC 4.2.1 (Apple Inc. build 5664)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> True = 4 File "<stdin>", line 1 SyntaxError: assignment to keyword

así el intérprete puede reemplazar el while True: loop con un ciclo infinito.


Esta es una pregunta de hace 7 años que ya tiene una gran respuesta, pero una idea errónea en la pregunta, que no se aborda en ninguna de las respuestas, la hace potencialmente confusa para algunas de las otras preguntas marcadas como duplicadas.

En otros contextos, Python actúa como si True es igual a 1:

>>> True == 1 True >>> True + True 2

¿Por qué mientras distingue a los dos?

De hecho, while no está haciendo nada diferente aquí en absoluto. Distingue 1 y True exactamente de la misma manera que el ejemplo + .

Aquí está 2.7:

>>> dis.dis(''True == 1'') 1 0 LOAD_GLOBAL 0 (True) 3 LOAD_CONST 1 (1) 6 COMPARE_OP 2 (==) 9 RETURN_VALUE >>> dis.dis(''True == 1'') 1 0 LOAD_GLOBAL 0 (True) 3 LOAD_GLOBAL 0 (True) 6 BINARY_ADD 9 RETURN_VALUE

Ahora compara:

>>> dis.dis(''1 + 1'') 1 0 LOAD_CONST 1 (2) 3 RETURN_VALUE

Está emitiendo un LOAD_GLOBAL (True) para cada True , y no hay nada que el optimizador pueda hacer con un global. Entonces, while distingue 1 y True por la misma razón que + hace. (Y == no los distingue porque el optimizador no optimiza las comparaciones).

Ahora compare 3.6:

>>> dis.dis(''True == 1'') 1 0 LOAD_CONST 0 (True) 2 LOAD_CONST 1 (1) 4 COMPARE_OP 2 (==) 6 RETURN_VALUE >>> dis.dis(''True + True'') 1 0 LOAD_CONST 1 (2) 2 RETURN_VALUE

Aquí, emite un LOAD_CONST (True) para la palabra clave, que el optimizador puede aprovechar. Entonces, True + 1 no distingue, por exactamente la misma razón, while True no lo hace. (Y == aún no los distingue porque el optimizador no optimiza las comparaciones).

Mientras tanto, si el código no se optimiza, el intérprete termina tratando True y 1 exactamente igual en los tres casos. bool es una subclase de int , y hereda la mayoría de sus métodos de int , y True tiene un valor entero interno de 1. Entonces, si estás haciendo una prueba __bool__ ( __bool__ en 3.x, __nonzero__ en 2.x), una comparación ( __eq__ ) o aritmética ( __add__ ), está llamando al mismo método si usa True o 1 .


Esto no está del todo bien,

así el intérprete puede reemplazar el tiempo True: loop con un ciclo infinito.

como uno todavía puede salir del circuito. Pero es cierto que nunca se accederá a la cláusula else ese bucle en Python 3. Y también es cierto que al simplificar la búsqueda de valor, se ejecuta tan rápido como while 1 en Python 2.

Comparación de rendimiento

Demostrando la diferencia en el tiempo para un ciclo while algo trivial:

Preparar

def while1(): x = 0 while 1: x += 1 if x == 10: break def whileTrue(): x = 0 while True: x += 1 if x == 10: break

Python 2

>>> import timeit >>> min(timeit.repeat(while1)) 0.49712109565734863 >>> min(timeit.repeat(whileTrue)) 0.756627082824707

Python 3

>>> import timeit >>> min(timeit.repeat(while1)) 0.6462970309949014 >>> min(timeit.repeat(whileTrue)) 0.6450748789939098

Explicación

Para explicar la diferencia, en Python 2:

>>> import keyword >>> ''True'' in keyword.kwlist False

pero en Python 3:

>>> import keyword >>> ''True'' in keyword.kwlist True >>> True = ''true?'' File "<stdin>", line 1 SyntaxError: can''t assign to keyword

Como True es 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 uno puede asignar True a otro valor, el intérprete debe buscarlo todo el tiempo.

Conclusión para Python 2

Si tiene un ciclo estrecho y prolongado en Python 2, probablemente debería usar while 1: lugar de while True: .

Conclusión para Python 3

Use while True: si no tiene ninguna condición para salir de su loop.