Calling __init__ with multiple inheritance

Michael Spencer mahs at telcopartners.com
Mon Mar 28 12:55:47 EST 2005


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




More information about the Python-list mailing list