Frage

eine Klasse Attribut aus einer Superklasse erbt und später den Wert für die Unterklasse zu ändern funktioniert:

class Unit(object):
    value = 10

class Archer(Unit):
    pass

print Unit.value
print Archer.value

Archer.value = 5

print Unit.value
print Archer.value

führt zum Ausgang:
10
10
10
5
das ist gut so: Archer den Wert von Einheit erbt, aber wenn ich Archer Wert, Unit Wert bleibt unberührt ändern.

Wenn nun der geerbten Wert eine Liste ist, die flache Kopie Effekt Streiks und den Wert der übergeordneten Klasse ist ebenfalls betroffen:

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

Ausgabe:
10
10
5
5

Gibt es eine Möglichkeit, „tiefe Kopie“ eine Liste, wenn es aus der Superklasse erben?

Vielen Dank
Sano

War es hilfreich?

Lösung

Es ist nicht eine Frage der flachen oder tiefer Kopien, ist es eine Frage der Referenzen und Zuweisungen.

Es ist der erste Fall Unit.value und Archer.value sind zwei Variablen, die den gleichen Wert verweisen. Wenn Sie Archer.value = 5 tun, zuweisen Sie einen neuen Verweis auf Acher.value.

Zur Lösung Ihres Problems benötigen Sie eine neue Liste Wert auf den Archer.list zuzuweisen.

Wenn diese Werte werden nur von Klassenmethoden zugegriffen gehen werden, dann ist die einfachste Lösung ist die Zuordnung zu tun, wenn die Klasse initialisiert wird.

Andere Tipps

Michael Antwort schön und einfach, aber wenn Sie möchten, um zu vermeiden, dass die Linie zu jeder Einheit Unterklasse hinzufügen - vielleicht haben Sie eine Reihe von anderen Listen wie, dass man, ist ein Metaklasse eine einfache Möglichkeit, das Problem zu lösen

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

Ausgabe:

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

Sie können auch diese gleiche Idee erweitern, um automatisch zu finden und kopieren Sie die Verzeichnisse (und dicts) definiert in Einheit

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

Sie können die Liste in der Definition von Archer kopieren:

class Archer(Unit):
    listvalue = Unit.listvalue[:]
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top