Je souhaite ajouter dynamiquement des attributs de classe à une super-classe. De plus, je veux créer des classes qui héritent dynamiquement de cette superclasse, et le nom de ces sous-classes devrait dépendre de l'entrée de l'utilisateur.Python: fabrique de classes utilisant l'entrée utilisateur comme noms de classes
Il existe une super-classe "Unit", à laquelle je peux ajouter des attributs lors de l'exécution. Cela fonctionne déjà.
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)
Cela conduit à la sortie désirée:
Strenght ofmyarcher: 5
Strenght ofmyarcher: 2
Mais maintenant, je ne veux pas prédéfinir la sous-classe Archer, mais je préfère laisser la l'utilisateur décide comment appeler cette sous-classe. J'ai essayé quelque chose comme ceci:
class Meta(type, subclassname):
def __new__(cls, subclassname, bases, dct):
return type.__new__(cls, subclassname, Unit, dct)
factory = Meta()
factory.__new__("Soldier")
mais pas de chance. Je suppose que je n'ai pas vraiment compris ce que nouveau fait ici. Ce que je veux à la suite est ici
class Soldier(Unit):
pass
créé par l'usine. Et si j'appelle l'usine avec l'argument "Chevalier", j'aimerais qu'une classe Chevalier, sous-classe d'Unité, soit créée.
Des idées? Merci d'avance!
Bye
-Sano
Merci Devin! Votre solution et celle de Felix semblent avoir un effet secondaire que je n'ai pas pris en compte: La nouvelle classe est un objet et doit être accrochée à quelque chose - stockée dans une varibale ou ajoutée à une liste ou à quelque chose. Je ne peux pas simplement créer la classe Knight, puis appeler le constructeur avec myKnight = Knight(). Plutôt, je dois faire quelque chose comme ceci: unitlist.append (meta ("Knight")) myKnight = unitlist [0]() Y a-t-il un moyen de contourner cela? Pour le dire franchement: Enregistrer la classe Knight à la même "position générale" la classe Unit est enregistrée lorsque sa définition est atteinte dans le code? – Sano98
@ Sano98: Je ne sais pas vraiment ce que tu veux dire. Vous pouvez faire 'Knight = meta (" Knight ")', puis faire 'myKnight = Knight()'. Que voulez-vous exactement? –
Merci, c'est exactement ce que je veux faire! Il suffit de l'enregistrer sous Knight ... Et puis c'est dans l'espace de noms global et je peux utiliser la classe comme si elle était codée en dur. Super merci. Je ne pensais tout simplement pas pouvoir appeler Chevalier() en sauvant la classe en tant que Chevalier, mais bien sûr, pourquoi pas? – Sano98