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: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
"""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
-- http://mail.python.org/mailman/listinfo/python-list
