Generic optional delegation: is it possible?

Alex Martelli aleax at aleax.it
Thu Mar 13 13:20:38 EST 2003


Eric Brunel wrote:
   ...
> I just stumbled on a problem and I can't see a way of doing it in an
> "elegant" way. Here it is: I have objects that may have another object
> attached to them. If this object is actually attached, I want all methods
> to be delegated to it. Otherwise, I want the object to call the methods on
> its super-class.

Having a superclass, as you've noticed, means automatic delegation and
thus in particular it means "having" all methods of the superclass.  If
you could avoid the inheritance, you'd therefore save yourself a lot of
trouble.  Still, even if you're doomed to inherit anyway, there may be
some solutions -- depending on the amount of (memory) overhead you're
able and willing to tolerate, and on whether you can do without special
methods (OR can stick with "classic classes", in which case the following
also works for special method -- for newstyle classes, you need a slightly
trickier solution based on a special-purpose dynamically generated class).

E.g.:

> class Delegating(SuperClass):
>    def __init__(self, delegate=None):
>      self.__delegate = delegate

add here (warning -- untested code):

       if self.__delegate:
           for name in dir(self):
               if hasattr(self.__delegate, name):
                   attrval = getattr(self.__delegate, name)
                   setattr(self, name, attrval)

key idea: "override" the superclass's attributes with the
similarly-named attributes of the delegate *in self*.  You
can also leave in the following:

>    def __getattr__(self, attr):
>      if self.__delegate is not None:
>        return getattr(self.__delegate, attr)

to catch attributes that are ONLY in the delegate and NOT
in the superclass, but you don't need the else branch:

>      else:
>        return getattr(SuperClass, attr)


> But it doesn't work: of course, object o1 *has* an attribute m (the method
> inherited from SuperClass), so __getattr__ doesn't get called.
> 
> Any ideas on how this can be achieved without having to type again all
> methods on my sub-class?

There are many other approaches, with different complications and
applicability, including __getattribute__ (for newstyle classes only)
and custom metaclasses (ditto).  Python's introspective abilities DO
ensure that you'll never need to "type again" such things;-).


Alex





More information about the Python-list mailing list