raw - Paso de Python por referencias
python string methods (3)
Como se indica here , CPython almacena en caché enteros de -5 a 256. Así que todas las variables dentro de este rango con el mismo valor comparten el mismo id (aunque no apostaría por las versiones futuras, pero esa es la implementación actual)
No existe tal cosa para los flotadores probablemente porque hay un "infinito" de valores posibles (bueno, no infinito sino grande debido al punto flotante), por lo que la posibilidad de calcular el mismo valor por diferentes medios es realmente baja en comparación con los enteros.
>>> a=4.0
>>> b=4.0
>>> a is b
False
Esta pregunta ya tiene una respuesta aquí:
- El operador “is” se comporta inesperadamente con enteros 11 respuestas
Hola, estoy tratando de entender cómo funciona el paso por referencia de Python. Tengo un ejemplo
>>>a = 1
>>>b = 1
>>>id(a);id(b)
140522779858088
140522779858088
Esto tiene mucho sentido ya que a y b hacen referencia al mismo valor que tendrían la identidad. Lo que no entiendo es cómo este ejemplo:
>>>a = 4.4
>>>b = 1.0+3.4
>>>id(a);id(b)
140522778796184
140522778796136
Es diferente de este ejemplo:
>>>a = 2
>>>b = 2 + 0
>>>id(a);id(b)
140522779858064
140522779858064
¿Se debe a que en el tercer ejemplo, el intérprete ve el objeto 0 int como "Ninguno" y no se reconoce que se necesite una identidad diferente del objeto al que se refiere la variable "a" (2)? Mientras que en el segundo ejemplo, "b" está agregando dos objetos int diferentes y el intérprete está asignando memoria para que se agreguen ambos objetos, lo que da a la variable "a", una identidad diferente de la variable "b"?
En su primer ejemplo, los nombres a
y b
son ambos "referenciando" al mismo objeto debido a la internación . La instrucción de asignación dio como resultado un entero con la misma id
solo porque ha reutilizado un objeto preexistente que ya estaba colgado en la memoria. Eso no es un comportamiento confiable de enteros:
>>> a = 257
>>> b = 257
>>> id(a), id(b)
(30610608, 30610728)
Como se demostró anteriormente, si elige un número entero lo suficientemente grande, entonces se comportará como se comportan los flotantes en su segundo ejemplo. Y la internación de pequeños enteros es opcional en el lenguaje Python, de todos modos, este es un detalle de implementación de CPython: es una optimización del rendimiento destinada a evitar la sobrecarga de crear un nuevo objeto. Podemos acelerar las cosas almacenando en caché las instancias de enteros comúnmente utilizadas, a costa de una mayor huella de memoria del intérprete de Python.
No piense en "referencia" y "valor" al tratar con Python, el modelo que funciona para C realmente no funciona bien aquí. En su lugar, piense en "nombres" y "objetos".
El diagrama de arriba ilustra tu tercer ejemplo. 2
es un objeto, b
son nombres. Podemos tener diferentes nombres que apuntan al mismo objeto. Y los objetos pueden existir sin ningún nombre.
Asignar una variable solo adjunta una etiqueta de nombre . Y eliminar una variable solo elimina una etiqueta de nombre . Si tienes esta idea en mente, el modelo de objetos de Python nunca más te sorprenderá.
Las variables de Python son siempre referencias a objetos. Estos objetos se pueden dividir en objetos mutables e inmutables.
Un tipo mutable se puede modificar sin que se modifique su ID, por lo que cada variable que apunta a este objeto se actualizará. Sin embargo, un objeto inmutable no se puede modificar de esta manera, por lo que Python genera un nuevo objeto con los cambios y reasigna la variable para que apunte a este nuevo objeto, por lo tanto, el ID de la variable antes del cambio no coincidirá con el ID de la variable después de el cambio.
Los enteros y los flotadores son inmutables, por lo que, después de un cambio, apuntarán a un objeto diferente y, por lo tanto, tendrán identificaciones diferentes.
El problema es que CPython "almacena en caché" algunos valores enteros comunes para que no haya varios objetos con el mismo valor para ahorrar memoria, y 2 es uno de esos enteros almacenados en caché, por lo que cada vez que una variable apunta al entero 2 tendrá el mismo ID (su valor será diferente para diferentes ejecuciones de Python).