[Python-Dev] PEP 318: Decorators last before colon

Phillip J. Eby pje at telecommunity.com
Wed Mar 31 12:32:35 EST 2004


At 04:38 PM 3/30/04 -0800, Guido van Rossum wrote:
> > > > Hm.  So if we reversed the order so that the outermost
> > > > decorators (such as classmethod) come first in the list, would
> > > > that sway you to relent in favor of decorators-after-arguments?
> > >
> > >Not really, because they're still hidden behind the argument list.
> >
> > Because:
> >
> > 1) it won't be on the same line if there are lots of arguments
> > 2) nobody will read past the argument list
> > 3) other
> > 4) all of the above
> > 5) none of the above
> >
> > (Not trying to change your opinion; I just think the answer to this should
> > go in the PEP.)
>
>1&2, mostly.

There appears to be a strong correlation between people who have specific 
use cases for decorators, and the people who want the last-before-colon 
syntax.  Whereas, people who have few use cases (or don't like decorators 
at all) appear to favor syntaxes that move decorators earlier.  Whether 
that means the "earlier" syntaxes are better or worse, I don't know.  <0.5 
wink>

I'll assume your intent is to prevent decorators from biting the unwary -- 
specifically people who *don't* use decorators a lot and therefore are not 
looking for them.  I will therefore focus now on the issues with the 
"previous line" syntax that may bite people, with an eye to how they might 
be fixed.


> > By the way, you didn't mention whether it's okay to put the decorators on
> > the same logical line, e.g.:
> >
> > [classmethod] def foo(bar,baz):
> >      # body goes here
> >
> > If the rationale here is that we're copying C#, I'd think that it
> > should be permissible, even though it looks a bit ugly and tempts me
> > to indent the body to align with the function name.
>
>This is much harder to do with the current parser.  (My plan would be
>to tie the list expression and the function definition together in the
>code generating phase, just like doc strings.)

Yeah, this is also going to now have to be a special case for documentation 
processing tools.  Whereas making it part of the definition syntax, it's 
more directly available in the parse tree.  It also seems to be working 
against the AST branch a bit, in that I would expect the decorator 
expressions to be part of the function definition node, rather than in an 
unrelated statement.  And, it's also going to be interesting to document in 
the language reference, since the grammar there is going to continue to 
diverge from the "real" grammar used by the implementation.

Another issue...  is this valid?

[classmethod]

def foo(bar,baz):
     pass

How about this?

[classmethod]
# Okay, now we're going to define something...
def foo(bar,baz):
     pass

If they *are* valid, then you can have nasty effects at a distance.  If 
they *aren't* valid, accidentally adding or removing whitespace or comments 
can silently change the meaning of the program, and *not* in a DWIMish way.

I personally would rather have the decorators required to be on the same 
logical line, and then use:

[classmethod] \
def foo(bar,baz):
     pass

for visual separation.  The backslash visually alerts that this is *not* a 
mere bare list.

I'm not a parser guru by any stretch of the imagination, but wouldn't it be 
possible to simply create a statement-level construct that was something like:

liststmt: '[' [listmaker] ']' ( funcdef | restofliststmt )

and put it where it matches sooner than the expression-based versions of 
the statement?  It seems like the main complexity would be the possibility 
of having to duplicate a number of levels of containing rules for 
'restofliststmt'.  But maybe I'm completely off base here and there's no 
sensible way to define a correct 'restofliststmt'.




More information about the Python-Dev mailing list