[Python-Dev] A usability argument for list-after-def

Phillip J. Eby pje at telecommunity.com
Thu Aug 5 22:48:09 CEST 2004


Guido has stated he'll accept one community syntax proposal as an 
alternative to "@".  He's also ruled out his own previous proposal 
(list-before-def), and a variety of new-keyword alternatives involving such 
things as 'as' and 'with'.

There doesn't appear to be a downside for decorator supporters to put forth 
another syntax, if they like it better than "@"; it seems the worst case is 
that we still end up with "@", if we end up with any syntax at all.

Of the options on the Wiki page ( at 
http://www.python.org/moin/PythonDecorators ), this seems to leave only 
list-after-def, the previous community favorite and the first PEP 318 
syntax to have been implemented.

Guido's principal argument against list-after-def, if I recall correctly, 
was that it is ugly when multiple or lengthy decorators are involved.  But, 
"ugly" isn't an argument any more, so that shouldn't rule out 
list-after-def.  :)

I only have one usability argument to favor list-after-def over "@": the 
former looks more like executable pseudocode than the latter.  If I pretend 
that I do not know Python, that I am a programmer who has never written in 
Python and is reading a Python program found in a magazine or downloaded 
from somewhere, then if I look at:

     @events.taskFactory
     def monitorProcess(self,process):
         ...

It is not immediately obvious that the previous line is part of the 
function definition; I am put off reading this code, because how do I know 
what "@" does?

Brackets are normally used in English to indicate an annotation or "aside" 
of some sort; such as a commentary *about* the surrounding material.  When 
I see this:

     def monitorProcess(self,process) [events.taskFactory]:
         ...

My impression is that the decorator is somehow annotating or subscripting 
the function.  In this specific example, I might wonder if this is how 
Python specifies a function return type.  But if I see:

     def do_something(cls,data) [classmethod]:
         ...

I am quickly alerted to this being some kind of annotation about the method 
itself, probably akin to public/private/static/friend etc. in other 
languages.  And, if I look for the definition of 'events.taskFactory' or 
'classmethod', I will quickly realize that this is an extensible annotation 
facility, as well.  By contrast:

     @classmethod
     def do_something(cls,data):
         ...

is also suggestive, but I personally find it far less conclusive, even with 
'classmethod' as a semantic cue.  Drawing on my experience of other 
languages and typical uses of "@", I think:

   * Is this some sort of array thing? (Perl)

   * Is this some sort of documentation tag? (Java...  but then I think no, 
it's not in a comment, so that can't be it)

   * Is this some sort of escape character for literate programming? (e.g. 
FunnelWeb and other such tools)

   * Is it being used in place of the word "at"?  (But what does it mean to 
be "at" a class method?  It's on a different line; surely if it were 
related there would be some sort of syntactic indication like indentation 
or a colon or braces or a comma or *something* between it and the definition?)

After some weighing of the evidence, I think I would most likely guess that 
this was some sort of documentation markup, rather than semantic 
markup.  But my train of thought in reading the code has now been quite 
disrupted, and if I was reading this code casually I might be discouraged 
from continuing, unless I had some reason for wanting to learn Python 
besides just reading the code in question or hacking up a quick fix to 
something.

Now, I don't know if my thought process here is at all typical or 
representative of anything, other than my own idiosyncratic self.  But, it 
is the one nagging thing that I have against "@", and I suspect that it may 
be implicitly behind a lot of the general outcry against it.  In other 
words, I think that "ugly" is just a pejorative term for the emotional 
reaction engendered by being forced to go through the above mental process 
for figuring it out.  And, to a lesser extent, I think list-before-def 
required some of the same mental processing overhead, although I personally 
think it was somewhat less than that of "@".

So there it is, my personal argument for list-after-def as better than "@", 
even if the list is over multiple lines: it's still much more clearly part 
of the function definition, and that IMO is the most important thing the 
syntax should convey, apart from listing the decorators themselves.



More information about the Python-Dev mailing list