Una asignación en python nunca crea una copia (es técnicamente posible solo si la asignación para un miembro de la clase se redefine, por ejemplo, usando __setattr__
, propiedades o descriptores).
Así que después de
a = foo()
b = a
todo lo que se volvió de foo
no se ha copiado, y en su lugar se tienen dos variables a
y b
que apuntan al mismo objeto. No importa si el objeto es inmutable o no.
Con objetos inmutables Sin embargo, es difícil saber si este es el caso (porque no se puede mutar el objeto con una variable y comprobar si el cambio es visible usando la otra) por lo que son libres de pensar que, efectivamente, a
y b
no puede influenciarse el uno al otro.
Para algunos objetos inmutables también Python es libre de volver a utilizar objetos antiguos en lugar de crear otros nuevos y después de
a = x + y
b = x + y
donde tanto x
y y
son números (por lo que la suma es un número y es inmutable) puede ser que tanto a
como b
apuntarán al mismo objeto. Tenga en cuenta que no existe tal garantía ... también puede ser que, en su lugar, apunten a diferentes objetos con el mismo valor.
Lo importante a recordar es que Python nunca hace una copia a menos que se indique específicamente el uso, p. copy
o deepcopy
.Esto es muy importante con objetos mutables para evitar sorpresas.
Una construcción común que se puede ver es por ejemplo:
class Polygon:
def __init__(self, pts):
self.pts = pts[:]
...
En este caso self.pts = pts[:]
se utiliza en lugar de self.pts = pts
para hacer una copia de toda la gama de puntos para asegurarse de que la lista de puntos no va a cambiar inesperadamente si después de crear el objeto, los cambios se aplican a la lista que se pasó al constructor.
Esto tiene muchas consecuencias prácticas. Considere la expresión comúnmente utilizada 'si la variable es None' ('None' es un objeto python inmutable incorporado y es importante si el objeto' es None' o simplemente se parece a 'None'). En principio, podrías hacer lo mismo con una cuerda que se ha apartado como especial. – mgilson
En realidad, hay muy pocas consecuencias prácticas al usar 'si x es None' contra' si x == None'. Solo se diferenciarán en casos de esquina extraños (por ejemplo, donde 'x' es un objeto que define una extraña prueba' __eq__'). Hay incluso una menor necesidad práctica de usar 'is' en cadenas y números. No se recomienda confiar en 'is' para strings/ints especiales" apartados "porque esta" anulación "depende de la implementación. – BrenBarn
Considere el caso común en el que usa 'if x is None:' para verificar si recibió un argumento de palabra clave. ¿Qué sucede si quiere aceptar 'None' como valor? Puedes hacer 'SENTINAL = ''; def foo (arg = SENTINAL); if (arg es SENTINAL): arg = [] 'por ejemplo. Esto no depende de la implementación. – mgilson