Automatic methods in new-style classes

Peter Otten __peter__ at web.de
Fri Sep 29 16:42:57 EDT 2006


bertgoos at yahoo.com wrote:

> Hey, I have the following code that has to send every command it
> receives to a list of backends. Instead of:
> 
> class MultiBackend(object):
>     """Renders to multiple backends"""
> 
>     def __init__(self, backends):
>         self.backends = backends
> 
>     def flush(self):
>         for b in self.backends:
>             b.flush()
> 
>     def draw(self):
>         for b in self.backends:
>             b.draw()
> 
> 
> I would like to write each method like:
> 
>     flush = multimethod()
> 
> Is that possible using new-style classes?

Not without a custom metaclass or the method name passed explicitly to
multimethod(). Here's a simpler approach that works with both new and
classic classes:

"""
>>> class B(object):
...     def __init__(self, name):
...         self.name = name
...     def draw(self, x, y):
...         print "%s: draw(%s, %s)" % (self.name, x, y)
...     def flush(self):
...         print "%s: flush()" % self.name

>>> m = MultiBackend([B("alpha"), B("beta")])
>>> m.draw(1, 2)
alpha: draw(1, 2)
beta: draw(1, 2)

>>> m.flush()
alpha: flush()
beta: flush()

"""

from operator import attrgetter

class MultiBackend(object):
    def __init__(self, backends):
        self._backends = backends
    def __getattr__(self, name):
        get = attrgetter(name)
        def multi(self, *args, **kw):
            for b in self._backends:
                get(b)(*args, **kw)
        setattr(self.__class__, name, multi)
        return getattr(self, name)

if __name__ == "__main__":
    import doctest
    doctest.testmod()

Peter



More information about the Python-list mailing list