sirve - python pdf
¿Por qué Python maneja ''1 es 1** 2'' de manera diferente a ''1000 es 10** 3''? (1)
Hay dos cosas separadas que suceden aquí: Python almacena literales int
(y otros literales) como constantes con código de int
compilado y los objetos enteros pequeños se almacenan en caché como singletons.
Cuando ejecuta 1000 is 1000
solo se almacena y se reutiliza una de estas constantes. Realmente estás mirando el mismo objeto:
>>> import dis
>>> compile(''1000 is 1000'', ''<stdin>'', ''eval'').co_consts
(1000,)
>>> dis.dis(compile(''1000 is 1000'', ''<stdin>'', ''eval''))
1 0 LOAD_CONST 0 (1000)
3 LOAD_CONST 0 (1000)
6 COMPARE_OP 8 (is)
9 RETURN_VALUE
Aquí LOAD_CONST
refiere a la constante en el índice 0; puede ver las constantes almacenadas en el atributo .co_consts
del objeto bytecode.
Compara esto con el 1000 is 10 ** 3
caso:
>>> compile(''1000 is 10**3'', ''<stdin>'', ''eval'').co_consts
(1000, 10, 3, 1000)
>>> dis.dis(compile(''1000 is 10**3'', ''<stdin>'', ''eval''))
1 0 LOAD_CONST 0 (1000)
3 LOAD_CONST 3 (1000)
6 COMPARE_OP 8 (is)
9 RETURN_VALUE
Hay una optimización de mirilla que calcula las expresiones en las constantes en el momento de la compilación, y esta optimización ha reemplazado 10 ** 3
por 1000
, pero la optimización no reutiliza las constantes preexistentes. Como resultado, los LOAD_CONST
están cargando dos objetos enteros diferentes, en el índice 0 y 3, y estos son dos objetos int
diferentes .
Luego hay optimizaciones en el lugar donde se internan los enteros pequeños ; solo se crea una copia del objeto 1
durante el tiempo de vida de un programa Python; esto se aplica a todos los enteros entre -5 y 256.
Por lo tanto, para el caso 1 is 1**2
, las partes internas de Python utilizan un objeto int()
singleton desde el caché interno. Este es un detalle de implementación de CPython.
La moraleja de esta historia es que nunca debes usarla cuando realmente quieres comparar por valor. Use ==
para enteros, siempre.
Inspirado por this pregunta sobre el almacenamiento en caché de enteros y cadenas pequeños, descubrí el siguiente comportamiento que no entiendo.
>>> 1000 is 10**3
False
Pensé que entendía este comportamiento: 1000 es demasiado grande para ser almacenado en caché. 1000 y 10 ** 3 puntos a 2 objetos diferentes. Pero lo tenía mal:
>>> 1000 is 1000
True
Por lo tanto, tal vez Python trate los cálculos de manera diferente a los enteros ''normales''. Pero esa suposición tampoco es correcta:
>>> 1 is 1**2
True
¿Cómo se puede explicar este comportamiento?