tutorial sirve que programacion para lista lenguaje español desde comandos cero python reference semantics python-internals

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?