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

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.

<later>

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