Python: Die Vererbung einer Klasse Attribut (Liste)
-
21-09-2019 - |
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
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[:]