Arthur said:
I must say that after days of waffling, and I think an honest effort
to accept where things were going, I woke this morning hating
@decorator.
The existing syntax for this kind of transformation is, in fact,
exactly what one would expect:
foo=staticmathed(foo).
That is the universal langauge for transformations. And when we try
to explain to anybody what it is that @decorator means, we go back to
the pseudo code that is in fact the existing syntax.
I'm with Arthur.
I think the core problem is that the def statement is kind of wierd. It
does two different things. First, it creates a function body, then it
binds the function to a name.
One of the objections to:
def foo ():
whatever
foo = decorator (foo)
is that you have to type the word "foo" three times. It's not so much
the effort of repeating the keystrokes, but the fact that it feels so
unfactored. The only reason you need to do this is because you have no
way of getting at the newly-generated function (what CS types would call
a "lambda form") before it's bound to the name.
A solution to that is to factor out the function definition from the
name binding, so you would do something like:
foo = def ():
whatever
although by the time you do that, you might as well have just gotten rid
of def and used lambda() directly. If you wanted it to be a
static/class method, you would do:
foo = staticmethod_def ():
whatever
The other big objection to the current syntax is that it puts the
wrapper way down at the bottom of the function body, away from the name.
The above syntax solves that too.
The big problem with the above is that it changes the semantics of the
def statement in a way which is incompatible with current usage, and
thus I would expect it's a complete non-starter. Not to mention
inventing new keywords.
On the other hand, doing:
def (staticmethod) foo ():
whatever
(you can pick whatever bits of punctuation turn you on) seems like it
should work just fine. I think it achieves all the goals:
1) It puts the decorator before the function body.
2) It keeps the decorator right next to the function name.
3) It doesn't re-define any currently valid syntax.
4) It looks enough like current Python syntax that most add-on tools
should handle it just fine.
5) If you've got lots of decorators (I'm still not sure if people really
think this will happen in real life), it's easy enough to break it up
into multiple lines:
def @decorator1 \
@decorator2 \
@decorator3 foo (a, b, c):
print a, b, c
but I'm assuming that will be the exception, just like really long
argument lists are the exception. Define the order of application of
multiple decorators in whichever way floats your boat; I'm guessing
outside-in (i.e. the last one gets done first) makes the most sense.
I suppose you could take this one step further and put the decorators
inside ()'s, so you'd have any of (as auto-indented by emacs):
def (decorator) foo (a, b, c):
pass
def (decorator1, decorator2, decorator3) foo (a, b, c):
pass
def (decorator1,
decorator2,
decorator3) foo (a, b, c):
pass
def (decorator1,
decorator2,
decorator3) foo (a,
b,
c):
pass
with the last example being a bit ugly, but at least it seems to follow
the expected indenting rules. In any case, you'd only have to resort to
something like that if you had lots of decorators and lots of arguments,
and in that case, I suspect you might want to be refactoring things to
simplify it all anyway.
I haven't done an exhaustive search of all the proposed syntaxen which
have come flying by here in the past week or so. My apologies if I've
accidentally duplicated somebody else's work here.
In retrospect (this has been written in dribs and drabs over the past
several hours, as I've been called away repeatedly to do real work), I
see I started out by agreeing with Arthur that the current (i.e. pre
PEP-318) way of doing things is good enough, then managed to head off
into a different direction and suggest YADS (Yet Another Decorator
Syntax). Oh, well.
I'm also not at all convinced that using decorators for things like doc
strings makes any sense at all. It's just the wrong tool. Docstrings
work just fine the way they are. If it ain't broke, don't fix it.
Which I guess brings me full-circle back to agreeing with Arthur