Python: Klasse Fabrik mit Benutzereingabe als Klassennamen
-
20-09-2019 - |
Frage
Ich will Klasse atttributes zu einer Super dynamisch hinzuzufügen. Darüber hinaus möchte ich Klassen erstellen, dass erben von dieser übergeordneten Klasse dynamisch, und der Name dieser Subklassen von Benutzereingaben abhängen sollte.
Es gibt eine übergeordnete Klasse „Einheit“, zu denen ich Attribute zur Laufzeit hinzufügen. Diese bereits funktioniert.
def add_attr (cls, name, value):
setattr(cls, name, value)
class Unit(object):
pass
class Archer(Unit):
pass
myArcher = Archer()
add_attr(Unit, 'strength', 5)
print "Strenght ofmyarcher: " + str(myArcher.strength)
Unit.strength = 2
print "Strenght ofmyarcher: " + str(myArcher.strength)
Dies führt zu dem gewünschten Ausgang:
Strenght ofmyarcher: 5
Strenght ofmyarcher: 2
Aber jetzt will ich nicht die Unterklasse Archer vordefinieren, aber ich möchte lieber der Benutzer entscheiden lassen, wie diese Unterklasse nennen. Ich habe so etwas wie dies versucht:
class Meta(type, subclassname):
def __new__(cls, subclassname, bases, dct):
return type.__new__(cls, subclassname, Unit, dct)
factory = Meta()
factory.__new__("Soldier")
aber kein Glück. Ich glaube, ich habe nicht wirklich verstanden, was neue hier der Fall ist. Was ich als Ergebnis will hier ist
class Soldier(Unit):
pass
wird vom Werk geschaffen. Und wenn ich das Werk mit dem Argument „Knight“ nennen, würde ich eine Klasse Ritter mögen, Unterklasse der Einheit, geschaffen werden.
Irgendwelche Ideen? Vielen Dank im Voraus!
Bye
-Sano
Lösung
Um eine Klasse von einem Namen zu erstellen, verwenden Sie die class
Anweisung und den Namen zuweisen. Beachten Sie:
def meta(name):
class cls(Unit):
pass
cls.__name__ = name
return cls
Nun nehme ich an, ich soll mich erklären, und so weiter. Wenn Sie eine Klasse erstellen, die Klasse Anweisung verwendet wird, wird es getan dynamically-- es Äquivalent des Aufrufs ist type()
.
Zum Beispiel die folgenden zwei Schnipsel das gleiche tun:
class X(object): pass
X = type("X", (object,), {})
Der Name einer class-- das erste Argument type-- zu __name__
zugeordnet ist, und das ist im Grunde das Ende, dass (das einzige Mal __name__
selbst verwendet wird, ist wahrscheinlich in der Standard-__repr__()
Implementierung). Um eine Klasse mit einem dynamischen Namen zu erstellen, können Sie in der Art der Tat Aufruf wie so, oder Sie können nur die Klassennamen später ändern. Die class
Syntax besteht aus einem Grund, though-- es bequem ist, und es ist einfach später zu und ändern die Dinge hinzuzufügen. Wenn Sie wollen Methoden hinzufügen, zum Beispiel, wäre es
class X(object):
def foo(self): print "foo"
def foo(self): print "foo"
X = type("X", (object,), {'foo':foo})
und so weiter. Also habe ich die Klasse statement-- verwenden würde Ihnen raten, wenn Sie gewusst hätte man so von Anfang an tun könnten, würden Sie wahrscheinlich getan haben. Der Umgang mit type
und so weiter ist ein Chaos.
(Sie soll nicht durch die Art und Weise, Call type.__new__()
von Hand, nur type()
)
Andere Tipps
Haben Sie einen Blick auf die type()
eingebaute Funktion.
knight_class = type('Knight', (Unit,), {})
- Erster Parameter: Name der neuen Klasse
- Zweiter Parameter: Tuple von Elternklassen
- Dritter Parameter:. Wörterbuch der Klasse Attribute
Aber in Ihrem Fall, wenn die Unterklassen vielleicht nicht ein anderes Verhalten implementieren, der Unit
Klasse Attribut eines name
geben ausreichend.