[Python-Dev] Class decorators
Jack Diederich
jack at performancedrivers.com
Thu Mar 30 03:00:59 CEST 2006
On Wed, Mar 29, 2006 at 07:23:03PM -0500, Phillip J. Eby wrote:
> At 11:07 AM 3/29/2006 -0800, Guido van Rossum wrote:
> >On 3/28/06, Phillip J. Eby <pje at telecommunity.com> wrote:
> > > If we're using Zope 3 as an example, I personally find that:
> > >
> > > class Foo:
> > > """Docstring here, blah blah blah
> > > """
> > > implements(IFoo)
> > >
> > > is easier to read than:
> > >
> > > @implements(IFoo)
> > > class Foo:
> > > """Docstring here, blah blah blah
> > > """
> >
> >But the former also smells more of magic.
>
> My comment above was only about readable *placement* of the decorators, not
> the actual syntax. Many approaches to the actual syntax in the body are
> possible.
>
> For example, what did you think of Fred Drakes's "@class" proposal? To
> specify it formally, one could say that this:
>
> @class EXPR
>
> in a class scope would expand to the equivalent of:
>
> locals().setdefault('__decorators__',[]).append(EXPR)
>
> and is a syntax error if placed anywhere else. That, combined with support
> for processing __decorators__ at class creation time, would fulfill the
> desired semantics without any implicit "magic".
>
A function decorator takes a function as an argument and returns something
(probably a function and maybe even the very same function).
This is exactly what class decorators should do or we should call them
something else and give them a distinct syntax.
A function decorator is there to replace code like:
def myfunc(a, b, c):
# half a screen of code
myfunc = mangle(myfunc)
Likewise class decorators would save me from typing
class MyClass:
# many functions taking half a screen of code each
register(MyClass, db_id=20)
I used to do this with metaclasses but stopped because it requires making
'db_id' a member of the class which is magically noticed by a metaclass
two files away. Using metaclasses also required gross hacks like checking
for a 'DO_NOT_REGISTER' member for subclasses that wanted to inherit from
a class that had a Register metaclass but didn't want to be registered.
Yuck.
If you want to do lots of Zopeish stuff mostly inside the class write
a decorator that looks for it in the class body.
@zope.find_magic_in_attr('mymagic')
class MyClass:
mymagic = [] # some long hairy thing
Talking about something other than a decorator or proposing all new
syntax is just going to get this pronounced out of existence.
If-I-wanted-zope-I'd-use-zope-ly,
-jackdied
More information about the Python-Dev
mailing list