PEP318

Roy Smith roy at panix.com
Thu Aug 12 12:33:50 EDT 2004


Arthur <ajsiegel at optonline.com> wrote:
> I must say that after days of waffling, and I think an honest effort
> to accept where things were going, I woke this morning hating
> @decorator.
> 
> The existing syntax for this kind of transformation is, in fact,
> exactly what one would expect:
> 
> foo=staticmathed(foo).
> 
> That is the universal langauge for transformations.  And when we try
> to explain to anybody what it is that @decorator means, we go back to
> the pseudo code that is in fact the existing syntax.

I'm with Arthur.

I think the core problem is that the def statement is kind of wierd.  It 
does two different things.  First, it creates a function body, then it 
binds the function to a name.

One of the objections to:

def foo ():
   whatever
foo = decorator (foo)

is that you have to type the word "foo" three times.  It's not so much 
the effort of repeating the keystrokes, but the fact that it feels so 
unfactored.  The only reason you need to do this is because you have no 
way of getting at the newly-generated function (what CS types would call 
a "lambda form") before it's bound to the name.

A solution to that is to factor out the function definition from the 
name binding, so you would do something like:

foo = def ():
   whatever

although by the time you do that, you might as well have just gotten rid 
of def and used lambda() directly.  If you wanted it to be a 
static/class method, you would do:

foo = staticmethod_def ():
   whatever

The other big objection to the current syntax is that it puts the 
wrapper way down at the bottom of the function body, away from the name.  
The above syntax solves that too.

The big problem with the above is that it changes the semantics of the 
def statement in a way which is incompatible with current usage, and 
thus I would expect it's a complete non-starter.  Not to mention 
inventing new keywords.

On the other hand, doing:

def (staticmethod) foo ():
   whatever

(you can pick whatever bits of punctuation turn you on) seems like it 
should work just fine.  I think it achieves all the goals:

1) It puts the decorator before the function body.

2) It keeps the decorator right next to the function name.

3) It doesn't re-define any currently valid syntax.

4) It looks enough like current Python syntax that most add-on tools 
should handle it just fine.

5) If you've got lots of decorators (I'm still not sure if people really 
think this will happen in real life), it's easy enough to break it up 
into multiple lines:

def @decorator1 \
    @decorator2 \
    @decorator3 foo (a, b, c):
   print a, b, c

but I'm assuming that will be the exception, just like really long 
argument lists are the exception.  Define the order of application of 
multiple decorators in whichever way floats your boat; I'm guessing 
outside-in (i.e. the last one gets done first) makes the most sense.

I suppose you could take this one step further and put the decorators 
inside ()'s, so you'd have any of (as auto-indented by emacs):

def (decorator) foo (a, b, c):
    pass

def (decorator1, decorator2, decorator3) foo (a, b, c):
    pass

def (decorator1,
     decorator2,
     decorator3) foo (a, b, c):
    pass

def (decorator1,
     decorator2,
     decorator3) foo (a,
                      b,
                      c):
    pass

with the last example being a bit ugly, but at least it seems to follow 
the expected indenting rules.  In any case, you'd only have to resort to 
something like that if you had lots of decorators and lots of arguments, 
and in that case, I suspect you might want to be refactoring things to 
simplify it all anyway.

I haven't done an exhaustive search of all the proposed syntaxen which 
have come flying by here in the past week or so.  My apologies if I've 
accidentally duplicated somebody else's work here.

In retrospect (this has been written in dribs and drabs over the past 
several hours, as I've been called away repeatedly to do real work), I 
see I started out by agreeing with Arthur that the current (i.e. pre 
PEP-318) way of doing things is good enough, then managed to head off 
into a different direction and suggest YADS (Yet Another Decorator 
Syntax).  Oh, well.

I'm also not at all convinced that using decorators for things like doc 
strings makes any sense at all.  It's just the wrong tool.  Docstrings 
work just fine the way they are.  If it ain't broke, don't fix it.  
Which I guess brings me full-circle back to agreeing with Arthur :-)



More information about the Python-list mailing list