Не мог придумать лучшего заголовка вопроса. Не стесняйтесь редактировать. У меня есть базовый класс, который унаследован многими классами (что, в свою очередь, может иметь больше подклассов). Для каждого класса у меня есть последовательность операций, которые мне нужно выполнить после инициализации. Последовательность инкапсулируется в функции runme()
, которая выполняет ряд метода объекта вызываетЧастично инициализирующий базовый класс
class myBase(object):
def __init__(self,neg,op,value):
self.neg = neg
self.op = op
self.value = value
#Process
self.runme()
def runme(self):
self.preprocess()
self.evaluate()
self.postprocess()
def preprocess(self):
pass
def evaluate(self):
pass
def postprocess(self):
pass
Подклассы должны принимать одни и те же атрибуты, что и основание (и любые дополнительные атрибуты). Все они будут чрезмерно ездить три функции - preprocess
, evaluate
и postprocess
class childA(myBase):
def __init__(self,neg,op,value,ad1):
super(childA,self).__init__(neg,op,value)
self.ad1 = ad1
#Must call runme() here again??
runme()
def evaluate():
#Something using self.ad1
blah = self.ad1+self.value
Как я понимаю, это создает проблему - childA
вызывает базу __init__
первый, который вызывает runme()
, который, в свою очередь, будет вызывать evaluate
. Поскольку ребенок чрезмерно едет evaluate
, определение ребенка в evaluate
выполняется, но self.ad1
не имеет еще был создан экземпляр, это бросает AttributeError
можно удалить self.runme()
из MyBase и проблема, скорее всего, исчезнет, но я может дополнительно sublcass childA
в childAA
class childAA(childA):
def __init__(self,neg,op,value,ad1):
super(childAA,self).__init__(neg,op,value,ad1)
self.runme()
И проблема может проявляться снова и снова. Я не могу удалить runme()
из childâ-х __init__
, потому что могут быть сформированы объекты как childA
и childAA
(и будут нуждаться в обработке)
В настоящее время в качестве обходного пути, я не называю runme()
в __init__
, вместо того, чтобы вызвать его из вызывающего после инициализации.
obja=childA(foo,bar,baz,ad1)
obja.runme()
Более простой альтернативой является вызов super()
в конце ребенка __init__
, но это не появляются быть правым
Другой способ - Скажите базовый класс отложить вызывания Runme() к дочернему классу. Это возможно? Скажем в myBase, я делаю
def __init__(self,neg,op,value):
self.neg = neg
self.op = op
self.value = value
#Process
if some_condition which checks if this is being called by a derived class:
self.runme()
Какой, если это лучший способ его решить? Альтернативно, это общая проблема и какие другие предлагаемые решения?
EDIT
Два ответа были опубликованы (и удален), который согласился лучшим способ, кажется, чтобы оставить runme()
вызов в базовом классе, а затем вызвать super()
на конце от ребенка __init__
class myBase(object):
def __init__(self,neg,op,value):
self.neg = neg
self.op = op
self.value = value
#Process
self.runme()
class childA(myBase):
def __init__(self,neg,op,value,ad1):
self.ad1 = ad1
super(childA,self).__init__(neg,op,value)
В случае, когда вам необходимо значения, которые зависят от существующих значений,
class childA(myBase):
def __init__(self,neg,op,value,ad1):
self.ad1 = ad1
self.internal_value = self.value #Not yet initialized!!
super(childA,self).__init__(neg,op,value)
этот код можно поместить в какой-либо другой функции preprocess()
или что вызывается первым в runme()
def preprocess(self):
self.internal_value = value
#Rest of the stuff
посмотреть http://rhettinger.wordpress.com/2011/05/26/super-considered-super/; Я думаю, что вообще нелогично называть 'super()' в конце, если '__init__' делегировать завершение инициализации класса. – thkang
Почему вы думаете, «что не может быть правильным»? Это именно то, что вам нужно в этом случае, и это самое простое решение. Я не вижу причин использовать очень сложный код только потому, что кто-то сказал вам, что решение _easy_ не кажется правильным. –
@ running.t Да, вы правы. На самом деле мое первоначальное решение не предусматривало удаления вызова 'runme()' от детей. Изменил мой вопрос, чтобы включить то, что я делаю сейчас, потому что два человека отправили один и тот же ответ, а затем удалили его – RedBaron