Я хочу иметь возможность создать экземпляр родительского класса X со строкой "Q" в качестве дополнительного аргумента.
Эта строка должна быть именем, являющимся идентификатором подкласса Q родительского класса X.< br> Я хочу, чтобы экземпляр родительского класса стал (или был заменен) экземпляром подкласса.
Я знаю, что это, вероятно, классическая проблема (ошибка?). Однако после некоторых поисков я не нашел подходящего решения.
Я сам придумал следующее решение:
я добавил словарь возможных идентификаторов в качестве ключей для их экземпляров базового класса в init strong>-метод родительского класса.
Затем присвоил class-атрибут соответствующего подкласса текущим экземплярам class-attribute.
Мне потребовался аргумент метода init не должен быть значением по умолчанию, чтобы предотвратить бесконечное зацикливание.
Ниже приведен пример того, как код выглядит на практике;
class SpecialRule:
""""""
name="Special Rule"
description="This is a Special Rule."
def __init__(self, name=None):
""""""
print "SpecialInit"
if name!=None:
SPECIAL_RULES={
"Fly" : FlyRule(),
"Skirmish" : SkirmishRule()
} #dictionary coupling names to SpecialRuleclasses
self.__class__= SPECIAL_RULES[name].__class__
def __str__(self):
""""""
return self.name
class FlyRule(SpecialRule):
""""""
name="Fly"
description="Flies."
def __init__(self):
""""""
print "FlyInit"+self.name
SpecialRule.__init__(self)
def addtocontainer(self, container):
"""this instance messes with the attributes of its containing class when added to some sort of list"""
class SkirmishRule(SpecialRule):
""""""
name="Skirmish"
description="Skirmishes."
def __init__(self):
""""""
SpecialRule.__init__(self)
def addtocontainer(self, container):
"""this instance messes with the attributes of its containing class when added to some sort of list"""
test=SpecialRule("Fly")
print "evaluating resulting class"
print test.description
print test.__class__
</pre></code>
вывод:
>
SpecialInit
FlyInitFly
SpecialInit
evaluating resulting class
Flies.
main.FlyRule
>
Есть ли более питоническое решение и есть ли предсказуемые проблемы с моим? (И я ошибаюсь, что хорошей практикой программирования является явный вызов .__init__(self)
родительского класса в .__init__
подкласса?). Мое решение кажется немного... неправильным...
Краткий обзор.
Спасибо за быстрые ответы.
@ Решение Марка Толонена
Я изучал __new__-method
, но когда я пытаюсь сделать A, B и C в примере Марка Толонена подклассами Z, я получаю сообщение об ошибке, что класс Z еще не определен. Также я не уверен, что создание экземпляра класса A обычным способом (с переменной=A() вне области Z) возможно, если только у вас уже не создан экземпляр подкласса и вы не вызываете класс как атрибут экземпляра подкласс Z... что не кажется очень простым. __new__
довольно интересен, поэтому я еще немного поиграю с ним, ваш пример легче понять, чем тот, что я получил из pythondocs.
@ Решение Грега Хьюгилла
Я попробовал решение staticmethod, и, похоже, оно работает нормально. Раньше я рассматривал возможность использования отдельной функции в качестве фабрики, но догадался, что будет сложно управлять большой программой со списком незакрепленных нитей кода конструктора в основном блоке, поэтому я очень рад интегрировать ее в класс.
Я немного поэкспериментировал, пытаясь превратить метод create в украшенный .__call__()
, но он получился довольно грязным, поэтому я оставлю его на этом.