2012-04-20 15 views
6

Mi clase representa estados de varios sistemas. Cada instancia tiene dos atributos: uno es un contenedor compartido entre todos los estados del mismo sistema, y ​​el otro es un contenedor que es único para cada instancia.copia versus deepcopy: semántica

Una copia de un estado debe reutilizar el atributo "compartido", pero cree una copia profunda del atributo "único". Esta es realmente la única semántica de copia que tiene sentido (es natural que la copia de un estado sea un estado del mismo sistema).

Quiero crear la menor sorpresa para las personas que leen y mantienen mi código. ¿Debo anular __deepcopy__ o __copy__ para mis propósitos?

+0

'__deepcopy__' si está tomando una encuesta ... –

+0

Bueno, esperaba una opinión consensuada :) Y aún puede ser, después de que todos tengan la oportunidad de ver la respuesta de todos. – max

Respuesta

3

¿Es realmente necesario utilizar el módulo de copia para copiar instancias de esta clase? Yo diría que en lugar de anular __copy__ o __deepcopy__, debe crear un método copy para su clase que devuelva un nuevo objeto utilizando la semántica de copia que definió.

Si por alguna razón de coherencia necesita usar el módulo de copia, entonces en mi opinión __deepcopy__ es más apropiado. Si es un comportamiento definido de la clase que todas las instancias compartan uno de los contenedores, entonces es razonable suponer que una implementación de __deepcopy__ lo respetaría.

+0

Estoy bien si no utilizo el módulo 'copy'. Pero si defino un método de 'copia', ¿no pensarían los lectores que es una copia superficial como lo es para 'dict' o' set'? – max

+0

@max, ¿su clase es una subclase de 'dict' o' set'? De lo contrario, los lectores no deberían suponer que se supone que un método de "copia" para su clase imita 'copiar' de un tipo incorporado. –

+0

@max: Creo que siempre sorprenderá a algunos lectores, ya que su semántica no es ni superficial ni completamente profunda. Pero de todos los lugares posibles para definir la semántica de copia personalizada, creo que el método de "copia" de una clase es el que es más probable que se personalice. Si la semántica completamente profunda y completamente profunda realmente * no tiene sentido * para su clase, entonces ¿por qué no anularlos a ambos? (Puede hacer que '__copy__' y' __deepcopy__' llamen a la 'copia' de la clase.) –

0

¿Es esto similar a tu situación?

import copy 

class Foo(object): 
    shared = [[]] 
    def __init__(self): 
     self.perinstance = [[]] 

Si es así, entonces parece que no es necesario definir __copy__ o __deepcopy__, ya que el comportamiento por defecto de los atributos de clase copy.deepcopy comparte atributos y deepcopies ejemplo:

x = Foo() 
z = copy.deepcopy(x) 
assert id(z.shared) == id(x.shared) 
assert id(z.shared[0]) == id(x.shared[0]) 
assert id(z.perinstance) != id(x.perinstance) 
assert id(z.perinstance[0]) != id(x.perinstance[0]) 
+0

Desafortunadamente, mi atributo compartido es un atributo de instancia. Yo era impreciso en mi explicación. El atributo "compartido" puede variar entre instancias, pero solo si corresponden a sistemas diferentes.La semántica de copia (como era de esperar) crea una copia de un estado del mismo sistema, por lo tanto, tiene el mismo valor que el atributo compartido. Estoy actualizando la pregunta para aclarar esto. – max