Domanda

ereditare un attributo di classe da una classe super e poi modificando il valore per la sottoclasse funziona bene:

class Unit(object):
    value = 10

class Archer(Unit):
    pass

print Unit.value
print Archer.value

Archer.value = 5

print Unit.value
print Archer.value

causa l'emissione:
10
10
10
5
che è solo bene: Archer eredita il valore unitario, ma quando cambio il valore di Archer, il valore di unità rimane intatta.

Ora, se il valore ereditato è una lista, gli scioperi effetto copia superficiale e il valore della superclasse è influenzato anche:

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

Output:
10
10
5
5

C'è un modo per "copia completa" un elenco quando eredita dalla classe super-?

Molte grazie
Sano

È stato utile?

Soluzione

Non è una questione di superficiale o copie profonde, si tratta di riferimenti e le assegnazioni.

E 'il primo caso Unit.value e Archer.value sono due variabili che fanno riferimento allo stesso valore. Quando si esegue Archer.value = 5, si sta assegnando un nuovo riferimento alla Acher.value.

Per risolvere il problema è necessario assegnare un nuovo valore alla lista Archer.list.

Se questi valori sono solo andando a essere accessibile da metodi di classe, quindi la soluzione più semplice è quello di fare l'assegnazione quando la classe viene inizializzato.

Altri suggerimenti

La risposta di Michael è bello e semplice, ma se si vuole evitare di dover aggiungere che la linea ad ogni sottoclasse Unit - forse avete un mucchio di altre liste come quella, un metaclasse è un modo semplice per risolvere il 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

uscita:

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

È inoltre possibile estendere la stessa idea di trovare automaticamente e copia fino liste (e dicts) definiti in Unità

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

Si potrebbe copiare l'elenco nella definizione di Archer:

class Archer(Unit):
    listvalue = Unit.listvalue[:]
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top