python - Partially initializing base class -
couldn't think of better question title. feel free edit. have base class inherited many classes (which in turn may have more sub-classes). each class, have sequence of operations need perform post-initialization. sequence encapsulated in function runme() performs series of object method calls
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 the sub-classes have accept same attributes base (and additional attributes). of them over-ride 3 functions - 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 the way see it, creates problem - childa calls base __init__ first, calls runme(), in turn call evaluate. since child over-rides evaluate, child's definition of evaluate executed, self.ad1 has not yet been instantiated, throws attributeerror
i can remove self.runme() mybase , problem gone, can further sublcass childa childaa
class childaa(childa): def __init__(self,neg,op,value,ad1): super(childaa,self).__init__(neg,op,value,ad1) self.runme() and problem can manifest on again. can't remove runme() childa's __init__ because objects of both childa , childaa can formed (and need processing)
currently, workaround, not call runme() in __init__, instead call calling program after initialization.
obja=childa(foo,bar,baz,ad1) obja.runme() a simpler alternative call super() @ end of child's __init__, not appear right
another way - tell base class defer calling of runme() child class. possible? in mybase, do
def __init__(self,neg,op,value): self.neg = neg self.op = op self.value = value #process if some_condition checks if being called derived class: self.runme() which if these best way solve it? alternatively, common problem , other suggested solutions?
edit
two answers posted (and deleted) concurred best way seems to leave runme() call in base-class , call super() @ end of child's __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) in case need values depend on existing values,
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) this code can put in preprocess() or other function gets called first in runme()
def preprocess(self): self.internal_value = value #rest of stuff
if children's __init__ require partially initialized objects proceed, calling super() @ end not work indeed. if that's case, call runme form __new__ in mybase:
class mybase(object): def __new__(cls, *args, **kwargs): obj = super(mybase, cls).__new__(cls) obj.__init__(*args, **kwargs) obj.runme() def __init__(self, a): print 'mybase init' self.list = ['mybase', a] def runme(self): print 'mybase:', self.list class childa(mybase): def __init__(self, a, b): print 'childa init' super(childa, self).__init__(a) self.list.extend(['childa', b]) def runme(self): print 'childa:', self.list class childaa(childa): def __init__(self, a, b, c): print 'childaa init' super(childaa, self).__init__(a, b) self.list.extend(['childaa', c]) def runme(self): print 'childaa:', self.list you can order code inside various __init__ functions required initialisation process, , proper runme function called after __init__ completes:
>>> childa(1, 2) childa init mybase init childa: ['mybase', 1, 'childa', 2] >>> childaa(1, 2, 3) childaa init childa init mybase init childaa: ['mybase', 1, 'childa', 2, 'childaa', 3]
Comments
Post a Comment