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