| Store | Cart

Calling __init__ with multiple inheritance

From: Michael Spencer <m...@telcopartners.com>
Mon, 28 Mar 2005 09:55:47 -0800
phil_nospam_schmidt at yahoo.com wrote:
> What if I want to call other methods as well? Modifying your example a> bit, I'd like the reset() method call of Child to invoke both the> Mother and Father reset() methods, without referencing them by name,> i.e., Mother.reset(self).> > -------------------> class Mother(object):>     def __init__(self, p_mother, **more):>         print "Mother", p_mother, more>         super(Mother, self).__init__(p_mother=p_mother, **more)>     def reset(self):>         print 'resetting Mother'> > class Father(object):>     def __init__(self, p_father, **more):>         print "Father", p_father, more>         super(Father, self).__init__(p_father=p_father, **more)>     def reset(self):>         print 'resetting Father'> > class Child(Mother, Father):>     def __init__(self, p_mother, p_father, **more):>         print "Child", p_mother, p_father, more>         super(Child, self).__init__(p_mother=p_mother,>                                     p_father=p_father, **more)>     def reset(self):>         print 'resetting Child'> >         # I would like to invoke both Mother.reset()>         # and Father.reset() here, but it doesn't work.>         print 'trying "super"'>         super(Child, self).reset()> >         # These next two do work, but require referencing>         # Mother and Father directly.>         print "calling directly">         Mother.reset(self)>         Father.reset(self)> > a = Child(1, 2)> a.reset()> -------------------> > Thanks,> Phil> 
if you're going to be doing a bunch of these, you could define your own variant 
of the super type that calls all the methods in the mro with the given name. 
Below is a minor modification to the pure-python version of built-in super that 
illustrates this.  There is no error-checking (e.g., if an attribute is callable 
in one class, and not callable in another you will hit problems) and it's not 
tested beyond what you see:

"""Hack on Super defined in http://python.org/2.2/descrintro.html
to call all super-class methods"""

class PolySuper(object):
     def __init__(self, type, obj=None):
         self.__type__ = type
         self.__obj__ = obj
     def __get__(self, obj, type=None):
         if self.__obj__ is None and obj is not None:
             return Super(self.__type__, obj)
         else:
             return self
     def __getattr__(self, attr):
         if isinstance(self.__obj__, self.__type__):
             starttype = self.__obj__.__class__
         else:
             starttype = self.__obj__
         mro = iter(starttype.__mro__)
         for cls in mro:
             if cls is self.__type__:
                 break
         # Note: mro is an iterator, so the second loop
         # picks up where the first one left off!
         for cls in mro:
             if attr in cls.__dict__:
                 x = cls.__dict__[attr]
                 if hasattr(x, "__get__"):
                     x = x.__get__(self.__obj__)

                 # return x
                 # We want all the resolved methods, in order
                 yield x
         #raise AttributeError, attr

     # Add this crude callable interface
     def __call__(self, attr, *args, **kw):
         methods = list(self.__getattr__(attr))
         return [method(*args, **kw) for method in methods]


Then, your classes get defined like so:

class Mother(object):
     def __init__(self, p_mother, **more):
         print "Mother", p_mother, more
     def reset(self):
         print 'resetting Mother'

class Father(object):
     def __init__(self, p_father, **more):
         print "Father", p_father, more
     def reset(self):
         print 'resetting Father'

class Child(Mother, Father):
     def __init__(self, p_mother, p_father, **more):
         print "Child", p_mother, p_father, more
         PolySuper(Child, self)("__init__", p_mother = p_mother, p_father = 
p_father)
     def reset(self):
         print 'resetting Child'
         PolySuper(Child, self)("reset")

  >>> c = Child("M1","F1")
  Child M1 F1 {}
  Mother M1 {'p_father': 'F1'}
  Father F1 {'p_mother': 'M1'}
  >>> c.reset()
  resetting Child
  resetting Mother
  resetting Father
  >>>

HTH
Michael

Recent Messages in this Thread
phil...@yahoo.com Mar 28, 2005 02:28 pm
Peter Otten Mar 28, 2005 03:10 pm
Michael Spencer Mar 28, 2005 05:55 pm
Messages in this thread