remaining decorator syntax options
bokr at oz.net
Wed Aug 11 02:12:44 CEST 2004
On 10 Aug 2004 12:33:36 -0700, steven.bethard at gmail.com (Steven Bethard) wrote:
>So here's the state of the decorator debate as I see it:
>GvR pretty strongly wants decorators before the function:
>The idea being that decorators and other function properties should
>not look like part of the function's code. I don't think there's much
>chance of swaying GvR on this count.
>Since location has been pretty much decided, I see three options here:
> def f():
Suggested indicator: '(=' or '(:' or '(%' e.g.,
>GvR definitely disliked the third version because it meant that class
>functions could all be at different indentation levels. The PEP
>suggests that the second version was disliked because it suggests that
>"using" is introducing a new scope (although arguments about if/else
>behavior seemed to counter this somewhat). There didn't seem to be
>any arguments that made version 2 drastically better than version 1
>though, so it seems most likely that a BDFL pronouncement will give us
>*** List notation
>Assuming a pre-def, non-indented decorator, here are the remaining
><indicator> [dec1, dec2, dec3]
><indicator> dec1, dec2, dec3
def f(): pass
>I believe that version 3 was vetoed because it makes it too hard to
>break lists of decorators across lines. GvR's preference is
>definitely for 1, but that may be influenced by his decision for the
>indicator. I have a feeling that how long the indicator is directly
>affects which of (1) or (2) is preferred. Compare:
>@[dec1, dec2, dec3]
>using [dec1, dec2, dec3]
>It seems like with a single symbol character, the non-list syntax is
>much more concise, and probably clearer. However with a keyword
>syntax the list seems the better option.
>Which brings us, of course to the final section:
>The options seemed to be:
>(1) a symbol (@, |, etc.)
>(2) a keyword (using, decorate, etc.)
>(3) similar to function
>(4) no indicator
(5) postfixed indicators [ (: (= (% <<< etc ]
def foo(): pass
>Options (3) and (4) were ruled out because (given that we're already
>relegated to a before-def syntax) they are already valid syntax, and
>redefining them for decorators means changing the expected semantics
>of the statements.
>Option (1), with @, is GvR's favorite, and does have something of a
>Java backing. It has the substantial disadvantage that there is no
>particular reason (or even some sort of mnemonic) for which @ (or |
>for that matter) should mean "decorator".
>With option (2), we can choose a keyword that does suggest a
>decorator. Even "using", which is not an outstanding choice, is at
>least more intuitive than '@'. Option (2) does have the disadvantage
>that it requires introducing a new keyword, but this is not
>insurmountable -- it was done before for generators. And GvR even
>said that he would consider this option if there enough support for
>So here's my suggestions:
>Let's leave the location and indentation arguments behind. We're not
>making much progress on them, and I don't think there's much chance of
>swaying GvR. Reiterating all the old arguments won't get us closer to
>a syntax we're happy with.
>I think once the indicator argument is decided, the list-structure
>decision will fall out of it.
>So I'd suggest that we put all our effort into the indicator
>discussions. If you have a good argument for why a keyword is better
>than a symbol, or why a symbol is better than a keyword, please voice
>them now. And remember that 'because it's prettier' or 'because it's
>uglier' are not aguments GvR will consider. We need strong arguments,
>that argue on the basis of readability or learnability or
You don't think GvR goes for prettier, other things being equal?
>... and my opinion:
>A keyword is much more Pythonic than a symbol:
Yes, except that what we have is really nested function calls,
passing a special argument, so maybe the decorating functions
ought to look like they are being invoked as functions. I.e.,
But, since it's not an ordinary argument list, we need an alternative
to the function-calling expression trailer (...) that yet suggests calling.
Since the def defines its own end, we don't need the )) above, but we do
need a different '(' -- so I'm suggesting (= or maybe (: or (% or <<<, so
the above simply becomes
and deco1 and deco2 can just be arbitrary expressions evaluating to something
If other statement:suite blocks can be interpreted as defining arguments useful
to pass to a function, then
could be used in a generalized way to operate on those. The loose end here is
re/binding the function (or class, etc) name. I.e., would you want to write
foo = deco1(=
foo = (
So long as postfixed (= is just sugar for the current use case,
it doesn't matter, of course. The rebinding can be a side effect
of an expression whose value is discarded.
>A well chosen keyword can suggest the meaning of the construction,
>e.g. "using ... def ..." suggests that the decorators are used as part
>of the definition of the function. A symbol like '@' or '|' cannot
>easily suggest the meaning in this manner.
But deco(...) suggests calling deco with something, and that's what's happening.
We just need to distinguish the def-result-as-argument variant, IMO.
>For this reason, a keyword makes both reading and learning Python
>decorator syntax easier. If you encounter "using ... def ..." and
>have to guess at it's meaning, your knowledge of English "using" can
>now be applied to guess the meaning of Python "using". This is not
>true of a symbol like '@' or '|'.
see above ;-)
>(An additional argument might be that it will be at least /possible/
>to Google "using", but impossible to do so for "@" or "|". This was
>one of the frustrating things about Perl for me -- if I didn't know
>what a symbol did, I couldn't Google it because it wasn't a word.
>Remember that if you don't know it's a decorator, you don't know to
>search for "decorate" ;)
I do like google. How about a postfixed keyword indicator like 'munges' ;-)
def foo(): pass
More information about the Python-list