[Python-Dev] Yet Another Decorator Syntax Suggestion (YADSS) (original) (raw)

Mike Thompson mike.spam.filter at day8.com.au
Mon Mar 29 02:11:09 EST 2004


I wonder if, as a lurker, I might make YADSS ... I'm not confident enough to argue my case too strongly, but thought I'd toss it into the ring as part of the creative process.

Background

I believe that cognitively speaking, when a function is first being understood by a reader, decorators need to be seen BEFORE the other details of the function (even its name). Understanding that a function is a 'classmethod', provides crucial context for understanding the function's name, argument list, documentation and body. So, I believe 'classmethod' should be seen first in the function definition.

I believe this requirement has motivated some to support syntax where the decorator list is promoted to be 'early' in the 'def': def [classmethod] func(args) OR def func [classmethod] func(args) etc.

That would be fine except that there is another 'competing' use case: once a function is known and understood, a programmer often needs to quickly look up its argument list.

This use case has tended to support syntax which places the function's decorators 'late' in the 'def', out the way, after the arguments:

 def func(args) [ decorators ]:

OR def func(args) as decorators:

I believe the 'syntactic tension' between these two use cases(1. first understanding, 2. later argument look up) will be impossible to resolve with any 'inline' syntax solution. (By 'inline' I mean syntax which tries to cram decorators into the 'def' line as is).

Finally, both the 'early' and 'late' decorator syntax have another problem: they don't scale nicely. The argument and decorator lists could be long; far too long for one line. That means the 'def' line has to be split and while solutions have been found for this in 'late' syntax form, I can't believe that anyone is really that happy with the look of the them. 'early' syntax and long decorator lists look particularly ugly, IMO.

YADSS

SO. For all these reason, I propose another approach. I'd argue that a multi line, more stuructured 'def' solution is required.

I propose that the 'as' keyword be used together with whitespace indentation before the 'def' to optionally decorate the def, something like this:

 as:
     classmethod
 def func(arg):
     pass

This solution scales up reasonably to multiple decorators:

 as:
     runOnExit
     staticmethod
     syncronisedWith(attr='lock')
     attributedBy(
         author='MT',
         release='5.4'
     )
     returns(int)
     takes((int, int))
 def func(args):
     pass

Can be used with classes as well ...

 as:
     providerOfInterface(IBar)
     syncronsiedWith(attr='_lock')
     singleton
 class K
     pass

For simple functions, perhaps the entire 'function header' can be folded onto two lines:

 as: classmethod
 def func(args)
     pass

OR, perhaps even one line (possible with parser?):

 as: classmethod def func(arg):
     pass

Not too sure about this last suggestion.

Pros

 - use of white space indentation and ':' consistent with
   other blocks in Python.
 - simple cases present simply, but it scales well to complex cases
 - places decorator upfront, but leaves function arg list easy
   to scan
 - does not require new keyword

Cons

 - 'as' might not be the perfect word.  Then again what would be?
 - some won't like that 'def' is not the first word in a definition

I hope this is useful food for thought, amongst those that know more (and do more for) Python than I.

Damn. I just re-read PEP-318 and found it included a syntax similar to that which I propose. Something from Quixote which uses 'using' where I have used 'as'.

I'm going to post this anyway because: 1. This approach is not getting much air-play and I belive it should; and 2. Because the use of 'as' I propose does not require a new keyword, which is a significant bonus over making a new keyword 'using'.

-- Mike



More information about the Python-Dev mailing list