@decorators
Mark Bottjer
mark_bottjer at hotmail.com
Fri Aug 6 13:48:55 EDT 2004
Tor Iver Wilhelmsen wrote:
> I think what he meant was that the decorators in effect make for
> "hidden continuation", e.g.
>
> @foo
> def fooDecorated():
> pass
>
> is like
>
> @foo def fooDecorated():
> pass:
>
> when other line continuations are explicit.
Which is *exactly* why I dislike this syntax so much. I don't mind the
"@", though it does look a might out-of-place. What I dislike is the
placement: It relies on setting a "magic state" in the interpreter to
affect the very next thing at the same indentation level. I can't think
of any other place in Python where this sort of thing is done.
Everything else either introduces a new block, or requires bracketing.
Everyone shows the examples like above, but what about the following?
class C:
# This is a really long comment that has little to do
# with the following function; it is here only so that
# the comment wraps. This is a really long comment that
# has little to do with the following function; it is
# here only so that the comment wraps over several lines.
@ staticmethod
# MAB 20040806113000: Added argument baz.
# MAB 20040806112957: Added argument bar.
# MAB 20040806112950: Initial version.
def static_method_foo( bar, baz):
pass
Did you catch it? This method *is* decorated, though it is hard to see
it unless you are really looking for it. Syntax coloring will help, of
course, but not much, and we shouldn't rely on that anyway.
My concern is that the decorator can be separated from the decorated by
an arbitrarily large amount of space. Even ONE blank line is enough for
me to mentally dissociate the decorator from the decorated. Comments
make it worse. Now, would a sane programmer do this? One would hope not,
but there is nothing to prevent it--and I've found that the definition
of "sane" varies widely between programmers.
What I think might work better is to treat these decorators the same way
we already treat docstrings.
def decorated( a, b, c):
@classmethod
@signature( None, a=int, b=float, c=dict)
@transactional( database)
"""\
decorated( a, b, c): A thrice-decorated function.
The silly function does nothing except get "decorated." classmethod
determines the form of the first argument (class, object, or
other). signature changes the call behavior, asserting the types
passed to and returned from the function. Finally, transactional
causes boilerplate code to be executed before and after the function
body, ensuring that either all changes to database are applied, or
none are. Seeing as this function does nothing, this is trivial :).
"""
pass
Personally, I kind of like the "@" syntax in this form. It still sticks
out (and IMHO, it *should* stick out, because it is not a normal
statement), but it also is easier to ignore if you aren't looking for it
because it is explicitly scoped at the function level.
We already expect metadata--namely, the docstring--to be at the top of
the function. This simply extends that idea to include other forms of
metafunctionality. The compiler already looks for metadata at the start
of functions; the special syntax helps the compiler determine which
statements need to be handled immediately, and where the function
implementation starts.
-- Mark
More information about the Python-list
mailing list