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

Popular posts from this blog

Why does Ruby on Rails generate add a blank line to the end of a file? -

keyboard - Smiles and long press feature in Android -

node.js - Bad Request - node js ajax post -