Pregunta

heredar un atributo de clase de una superclase y luego cambiando el valor de la subclase funciona bien:

class Unit(object):
    value = 10

class Archer(Unit):
    pass

print Unit.value
print Archer.value

Archer.value = 5

print Unit.value
print Archer.value

conduce a la salida:
10
10
10
5
Lo que está bien: Archer hereda el valor de la Unidad, pero cuando cambio el valor de Archer, el valor de unidad permanece intacta.

Ahora, si el valor heredado es una lista, los ataques de efecto copia superficial y el valor de la superclase también se ve afectada:

class Unit(object):
    listvalue = [10]

class Archer(Unit):
    pass

print Unit.listvalue
print Archer.listvalue

Archer.listvalue[0] = 5

print Unit.listvalue
print Archer.listvalue

Salida:
10
10
5
5

¿Hay una manera de "copia en profundidad" una lista cuando heredarlo de la superclase?

Muchas gracias
Sano

¿Fue útil?

Solución

No es una cuestión de poca profundidad o copias profundas, es una cuestión de referencias y asignaciones.

Es la primera Unit.value caso y Archer.value son dos variables que hacen referencia al mismo valor. Cuando lo haga Archer.value = 5, está asignando una nueva referencia a Acher.value.

Para resolver el problema es necesario asignar un nuevo valor a la lista de Archer.list.

Si estos valores sólo van a ser visitada por métodos de clase, a continuación, la solución más simple es hacer la asignación cuando se inicializa la clase.

Otros consejos

La respuesta de Michael es agradable y simple, pero si usted desea evitar tener que añadir esa línea para cada subclase Unidad - tal vez usted tiene un montón de otras listas como esa, una metaclase es una manera fácil de resolver el problema

class UnitMeta(type):
    def __init__(self, *args):
        super(UnitMeta, self).__init__(*args)
        self.listvalue = [10]

class Unit(object):
    __metaclass__ = UnitMeta
    pass

class Archer(Unit):
    pass

print Unit.listvalue
print Archer.listvalue

Archer.listvalue[0] = 5

print Unit.listvalue
print Archer.listvalue

salida:

[10]
[10]
[10]
[5]

También puede extender esta misma idea de encontrar automáticamente y copiar las listas (y predice) definidas en la unidad

class UnitMeta(type):
    def __init__(self, *args):
        super(UnitMeta, self).__init__(*args)
        for superclass in self.__mro__:
            for k,v in vars(superclass).items():
                if isinstance(v, (list, dict, )):
                    setattr(self, k, type(v)(v))

class Unit(object):
    __metaclass__ = UnitMeta
    listvalue = [10]

class Archer(Unit):
    pass

Se puede copiar la lista en la definición de Archer:

class Archer(Unit):
    listvalue = Unit.listvalue[:]
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top