[Python-Dev] Use case for class decorators

Goncalo Rodrigues op73418 at mail.telepac.pt
Thu Apr 15 15:22:00 EDT 2004


Here is a use case for class decorators.

I find myself writing a lot of proxies and adapters. Usually, they are just a 
subclass of something as simple as

class Proxy(object):
    """The Proxy base class."""

    def __init__(self, obj):
        """The initializer."""
        super(Proxy, self).__init__(obj)
        #Private attributes.
        self.__obj = obj

    #Read-only properties.
    __obj__ = property(lambda self: self.__obj,
                       doc = "The underlying object of the Proxy.")

    def __repr__(self):
        return "%s(%r)" % (self.__class__.__name__,
                           self.__obj__)

    def __getattr__(self, attrib):
        return getattr(self.__obj__, attrib)

This is all fine and dandy, except that no magic methods are trapped. Usually, 
I just inject them directly after the class statement via:

#Auxiliary getter function.
def getter(attrib):
    return lambda self, *args, **kwargs: getattr(self.__obj__, attrib)(*args, 
**kwargs)


def inject(cls, magicnames):
    """Inject magic methods directly in a class.

    Warning(s):
    - Only magic names are injected.
    - Does not overwrite already present magic names.
    """
    for magicname in magicnames:
        if magicname.startswith("__") and magicname.endswith("__"):
            if not hasattr(cls, magicname):
                setattr(cls, magicname, getter(magicname))

The function inject is a use case for a class decorator. If it's a good use 
case that's something I'll leave you to argue at will (<runs away>). I think 
it's fairly obvious that using a metaclass to do this simple operation is a 
clear case of the wrong tool for the job.

With my best regards,
G. Rodrigues

p.s: 
<comment on syntax>
The syntax for decorators:

[dec1, dec2, ...]
def foo(arg1, arg2, ...):
    pass

is probably the worst of all syntaxes (with appologies for my bluntness). It 
just doesn't parse well. What I see in the above proposed syntax is just a list 
literal and a definition statement. There's no indication that the two are 
somehow linked (I can't express this any better, English is not my native 
lingo).

The best, IMHO is

def foo(arg1, arg2, ...) [dec1, dec2, ...]:
    pass

<\ comment on syntax>




More information about the Python-Dev mailing list