[Python-Dev] A usability argument for list-after-def (original) (raw)

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:

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