Me gustaría crear una copia de un objeto. Quiero que el nuevo objeto posea todas las propiedades del objeto antiguo (valores de los campos). Pero quiero tener objetos independientes. Entonces, si cambio los valores de los campos del nuevo objeto, el objeto antiguo no debería verse afectado por eso.
200
Te refieres a un objeto mutable entonces.
En Python 3, las listas obtienen un
copy
método (en 2, usaría un segmento para hacer una copia):Copias superficiales
Las copias superficiales son solo copias del contenedor más externo.
list.copy
es una copia superficial:No obtienes una copia de los objetos interiores. Son el mismo objeto, por lo que cuando están mutados, el cambio se muestra en ambos contenedores.
Copias profundas
Las copias profundas son copias recursivas de cada objeto interior.
Los cambios no se reflejan en el original, solo en la copia.
Objetos inmutables
Los objetos inmutables generalmente no necesitan copiarse. De hecho, si lo intentas, Python solo te dará el objeto original:
Las tuplas ni siquiera tienen un método de copia, así que probémoslo con un segmento:
Pero vemos que es el mismo objeto:
Del mismo modo para cadenas:
y para congelados, a pesar de que tienen un
copy
método:Cuando copiar objetos inmutables
Los objetos inmutables deben copiarse si necesita un objeto interior mutable copiado.
Como podemos ver, cuando el objeto interior de la copia está mutado, el original no cambia.
Objetos personalizados
Los objetos personalizados generalmente almacenan datos en un
__dict__
atributo o en__slots__
(una estructura de memoria tipo tupla).Para hacer un objeto copiable, defina
__copy__
(para copias superficiales) y / o__deepcopy__
(para copias profundas).Tenga en cuenta que
deepcopy
mantiene un diccionario de memorización deid(original)
(o números de identidad) para las copias. Para disfrutar de un buen comportamiento con estructuras de datos recursivas, asegúrese de que aún no haya hecho una copia y, si la tiene, devuélvala.Entonces hagamos un objeto:
Y
copy
hace una copia superficial:Y
deepcopy
ahora hace una copia profunda:fuente
Copia superficial con
copy.copy()
Copia profunda con
copy.deepcopy()
Documentación: https://docs.python.org/3/library/copy.html
Probado en Python 3.6.5.
fuente
Creo que lo siguiente debería funcionar con muchos de buen comportamiento clasificados en Python:
(Por supuesto, no estoy hablando aquí de "copias profundas", que es una historia diferente y que puede no ser un concepto muy claro: ¿qué tan profundo es lo suficientemente profundo?)
Según mis pruebas con Python 3, para objetos inmutables, como tuplas o cadenas, devuelve el mismo objeto (porque no hay necesidad de hacer una copia superficial de un objeto inmutable), pero para listas o diccionarios crea una copia superficial independiente .
Por supuesto, este método solo funciona para clases cuyos constructores se comportan en consecuencia. Posibles casos de uso: hacer una copia superficial de una clase de contenedor Python estándar.
fuente
__init__
método. Entonces, pensé que este método puede ser lo suficientemente bueno para ciertos fines. En cualquier caso, me interesarán los comentarios informativos sobre esta sugerencia.class Foo(object): def __init__(self, arg): super(Foo, self).__init__() self.arg = arg
básico como se pone. Si lo hagofoo = Foo(3) bar = copy(foo) print(foo.arg) # 3 print(bar.arg) # <__main__.Foo object at ...>
Significa que sucopy
función está rota incluso para las clases más básicas. Nuevamente, es un buen truco (por lo tanto, no DV), pero no una respuesta.copy.copy
método para hacer copias superficiales, pero, tal vez ingenuamente, me parece que debería ser responsabilidad de la clase proporcionar un "constructor de copias superficiales". En tal caso, ¿por qué no proporcionarle el mismo tipo de interfaz quedict
ylist
hacer? Entonces, si su clase quiere asumir la responsabilidad de copiar sus objetos, ¿por qué no agregar unaif isinstance(arg, type(self))
cláusula__init__
?