By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,948 Members | 838 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,948 IT Pros & Developers. It's quick & easy.

Decorator syntax

P: n/a

I vote for

def f(): [synchronized, classmethod]
(body of function)

This is backwards compatible (Python <= 2.3 raise
SyntaxError), and looks much nicer than @.

The only problem is that you can't one-line a
decorated function. You can't do that with
the @ notation either, so it's not a big deal.

- Connelly

__________________________________
Do you Yahoo!?
New and Improved Yahoo! Mail - 100MB free storage!
http://promotions.yahoo.com/new_mail
Jul 18 '05 #1
Share this Question
Share on Google+
23 Replies


P: n/a
C. Barnes wrote:
I vote for

def f(): [synchronized, classmethod]
(body of function)

This is backwards compatible (Python <= 2.3 raise
SyntaxError), and looks much nicer than @.


I'm nearly certain, without bothering to check, that this
was one of the many proposals already discussed and rejected,
if nothing else for the simple reason that it only works
nicely when you have a short definition such as your example
(with "f()") and not nicely at all with a much longer name
and argument list. Inevitably you would need to split the
decorator part onto a second line, either requiring a
backslash (ugly) or changing your second comment about it
raising a SyntaxError with previous versions (because it
then matches valid though meaningless code).

Anyway, check the past discussions before going back around
the same arguments yet again.

For the record, the @ syntax is despicable and horribly
un-Pythonic, IMHO, and I really hope never to read code that
uses it. :-(

(And my preferred syntax was "def f() [classmethod]:", FWIW)

-Peter
Jul 18 '05 #2

P: n/a
"Peter Hansen" <pe***@engcorp.com> wrote in message
news:38********************@powergate.ca...
<snip>
For the record, the @ syntax is despicable and horribly
un-Pythonic, IMHO, and I really hope never to read code that
uses it. :-(

(And my preferred syntax was "def f() [classmethod]:", FWIW)


Agreed. And I also like your preferred syntax - clear, readable, no
eye-jarring symbols.

The references to Java and C# as justification or rationale for using @
remind me of when I lived in Maine. When I complained about how bad the
drivers were, inevitably the response was "we're not as bad as the drivers
in Massachusetts!"

If this was some impulsive lurch forward to just pick something and proceed,
I think we are seeing another backtick in the making.

I fear that $, ^ and ~ are just around the corner.

-- Paul
Jul 18 '05 #3

P: n/a
On Thu, Aug 05, 2004 at 04:25:13AM +0000, Paul McGuire wrote:
[...]

I fear that $, ^ and ~ are just around the corner.


No need to fear: ^ and ~ are already there.
~1 -2 1^2

3

-Andrew.

Jul 18 '05 #4

P: n/a
"Paul McGuire" <pt***@austin.rr._bogus_.com> wrote in message news:<JE*****************@fe2.texas.rr.com>...
"Peter Hansen" <pe***@engcorp.com> wrote in message
news:38********************@powergate.ca...
<snip>
For the record, the @ syntax is despicable and horribly
un-Pythonic, IMHO, and I really hope never to read code that
uses it. :-(

(And my preferred syntax was "def f() [classmethod]:", FWIW)


Agreed. And I also like your preferred syntax - clear, readable, no
eye-jarring symbols.


That's what I think too. If there has to be a decorator syntax (other
than present "f = decor(f)" rebinding, which makes the process of
decorating as explicit as it gets), that's the one to go.

Effbot's expression of horror at the @ syntax was no surprise to me,
although sudden appearance of the latter was. I read somewhere that
the BDFL allowed this patch because he was tired with the long,
never-ending discussion. I have this conspiracy theory that he did so
to stirr the community and finally get some clear response on what's
best. Which might be a risky but good move.

Which made me think: I'd rather know when I'm losing perspective (and
be able to remedy that) than just try not to lose it.

AdSR
Jul 18 '05 #5

P: n/a
> Anyway, check the past discussions before going back around
the same arguments yet again.


And exactly how is one supposed to do this? I would have thought the pep
would be the place to start, but pep 318 is actively misleading as to the
state of the project.

BTW, one of the design goals in pep 318 is "not needlessly complicate
secondary support tools". I would classify Leo as one of those tools, and
the '@' syntax threatens Leo directly, as I have said in the thread called
"Confused about pep 318"

Edward
--------------------------------------------------------------------
Edward K. Ream email: ed*******@charter.net
Leo: Literate Editor with Outlines
Leo: http://webpages.charter.net/edreamleo/front.html
--------------------------------------------------------------------
Jul 18 '05 #6

P: n/a
Edward K. Ream wrote:
Anyway, check the past discussions before going back around
the same arguments yet again.


And exactly how is one supposed to do this? I would have thought the pep
would be the place to start, but pep 318 is actively misleading as to the
state of the project.


I'm pretty sure it would involve using Google Groups and keywords
such as "decorator syntax", but I haven't personally tried. I can
provide remedial instruction to those who try the above and
variations on it but who are still unable to find *any* past
discussions of this topic. ;-)

-Peter
Jul 18 '05 #7

P: n/a
On Thu, 5 Aug 2004, Paul McGuire wrote:
remind me of when I lived in Maine. When I complained about how bad the
drivers were, inevitably the response was "we're not as bad as the drivers
in Massachusetts!"


I believe that statement is universally true ;)

I think much of the problem in coming up with a universally acceptable
decorator solution is that we're trying to kill too many birds with one
stone. I believe the decorator problem can be seperated into at least
three distinct needs:
1) An easy, visually noticable way of declaring the type of a function,
such as classmethod and staticmethod.

This problem arose because classmethod and staticmethod weren't built
in to the language. The foo = classmethod(foo) syntax is a
backwards-compatible hack, not the best way to do things. For such a
fundamental construct, we need language support. Languages with support
for these things already have a clear, consice way of specifying these
things:

def classmethod foo(self):
pass

Why can't we do the same with Python? The syntax doesn't have to
support user constructs (indeed, it shouldn't), and it doesn't have to
support more than one decorator (indeed, with only classmethod
and staticmethod to choose from, this doesn't even make sense).
2) An easy, visually unobtrusive way of declaring metadata.

This is a problem we've encountered before. The solution was to make a
string at the top of the function behave as metadata, rather than code.
Perhaps something similar can be done with a dictionary:

def foo(a,b,c):
{accepts: (int,int,list), author: 'Chris King'}
pass

foo.__metadata__['accepts'] --> (int,int,list)

Note that such a method is implementable in pure Python via some
byte-code trickery, and can thusly be made backwards-compatible.

Another (perhaps better) method of declaring metadata has been previously
proposed, that of function attributes:

def foo(a,b,c):
.accepts = (int,int,list)
.author = 'Chris King'

but this proposal has also (sadly) been previously rejected, despite its
elegance and similarity to proposed "with" blocks.
3) An easy, visually noticable, yet unobtrusive way of mangling functions:

Doing such a thing, IMO, should not have syntax support. When functions
are mangled in a user-defined way, it should look like this is happening.
Why not make it convenient and wrap in up in a function:

def foo(a,b,c):
pass

mutate(foo, make_my_function_awesome, partializer(5))

This has the advantage of being more general-purpose than syntax support:
say make_my_function_awesome is not available, so a NameError is raised.
The user can simply skip using that function in that case. Or the
existence of make_my_function_awesome can be checked beforehand, and left
out of the mutate call if it's not available.

If syntax support is used, there's no way to try/except function manglers,
save try/excepting the entire function defintion (and forcing multiple
identical versions of the function to be defined). Quite ugly.
So, to sum it up, let's look at what a totally pimped-out function might
look like:

def classmethod foo(self,a,b,c):
"""Returns a+b*c."""
{accepts: (int,int,int), author: 'Chris King'}

return a+b*c

mutate(foo, make_my_function_awesome, partializer(5))

Compare to the current state of affairs:

@partializer(5)
@make_my_function_awesome
@author('Chris King')
@accepts(int,int,int)
@classmethod
def foo(self,a,b,c):
"""Returns a+b*c."""

return a+b*c

Judge for yourself.

Jul 18 '05 #8

P: n/a
Christopher T King wrote:
Languages with support
for these things already have a clear, consice way of specifying these
things:

def classmethod foo(self):
pass

Why can't we do the same with Python? The syntax doesn't have to
support user constructs (indeed, it shouldn't), and it doesn't have to
exactly my thoughts,

but then someone comes along and vehemently argues
how this will break Emacs or Jedit and on top of that
it won't allow you to do some *really cool* stuff, like
multi-decorations for a truly pythonic iteration over
the AccuWeather 10 day forecast datadump.
Compare to the current state of affairs: @partializer(5)
@make_my_function_awesome
@author('Chris King')
@accepts(int,int,int)
@classmethod
def foo(self,a,b,c):
"""Returns a+b*c."""

return a+b*c


Yuck! Down with them funny symbols!

i.

Jul 18 '05 #9

P: n/a
C. Barnes <co************@yahoo.com>
wrote on Wed, 4 Aug 2004 18:42:48 -0700 (PDT):
I vote for
def f(): [synchronized, classmethod]
(body of function)
That syntax looks plausible in toy examples, but is terrible for a
more typical invocation, like:

class foo:
def introduceNewFeature(self, someArgument, anotherArgument): [synchronized, types="o,i,i"]
pass # whatever
This is backwards compatible (Python <= 2.3 raise
SyntaxError),
That's not what "backwards compatible" means, but @-syntax also raises
a syntax error in older versions, which is just what you'd expect.
and looks much nicer than @.
I fail to see how that's more attractive than:

class foo:
@synchronized
@types("o,i,i")
def introduceNewFeature(self, someArgument, anotherArgument):
pass # whatever

I'm +1 for the @-syntax.

1) It doesn't cause needless line-wrap.
2) It causes the minimum amount of confusion, because it doesn't
overload an existing symbol. [] and {} and () are already pushed to
their limits and beyond in Python. Give them a day off for once.
3) A large proportion of Python programmers are also Java programmers,
and won't object to the @-syntax.
The only problem is that you can't one-line a
decorated function. You can't do that with
the @ notation either, so it's not a big deal.


One-liners are of negative value to a language, anyway, as they
encourage bad habits. That way lies Perl and other juvenile
entertainments.

--
<a href="http://kuoi.asui.uidaho.edu/~kamikaze/"> Mark Hughes </a>
"Virtues foster one another; so too, vices.
Bad English kills trees, consumes energy, and befouls the Earth.
Good English renews it." -The Underground Grammarian, v1n2
Jul 18 '05 #10

P: n/a
Mark 'Kamikaze' Hughes wrote:

class foo:
def introduceNewFeature(self, someArgument, anotherArgument): [synchronized, types="o,i,i"]
pass # whatever
Those who need argument type-checking should
go to Guido and talk to him about it. Piggybacking
this in as decorators makes everybody lose.
3) A large proportion of Python programmers are also Java programmers,
and won't object to the @-syntax.


yay. love is in the air.

Istvan.

Jul 18 '05 #11

P: n/a
"Andrew Bennetts" <an***************@puzzling.org> wrote in message
news:ma**************************************@pyth on.org...
On Thu, Aug 05, 2004 at 04:25:13AM +0000, Paul McGuire wrote:
[...]

I fear that $, ^ and ~ are just around the corner.


No need to fear: ^ and ~ are already there.
~1 -2 1^2

3

-Andrew.


Ooops, duh! I guess I meant "$ and ?".

As this discussion wears on (and on...), there are several comments to the
effect of "let's save @ for something really important, and not waste it on
decorators." Personally, I've enjoyed the clean look of Python source that
isn't splattered with special @'s and $'s. I *don't* want to save @ for
something important, I'd prefer to see it kept out of the syntax altogether,
along with $. (Oddly, I don't find ? near as ugly, but I wouldn't suggest
it as an alternative to @ as a decorator-introducer.)

I don't see this as merely a personal style choice either, as in "if you
don't like @'s, don't use @'s" - it seems to me that the emergence of a
decorator syntax means that I'll at some point have to use them to replace
the deprecated staticmethod and classmethod keywords.

@ and $ evoke the old days of job control commands and all-caps coding in
Cobol and FORTRAN - anyone care for code like:

@SYNCHRONIZED
DEF UPDATE_COUNT(SELF):
SELF.COUNT = SELF.COUNT + 1

It seems to me that historically Python has eschewed using special
characters in other cases. For instance, rather than mark instance methods
of a class with some magic character (such as '>', say), they contain an
explicit 'self' argument (whether this is good or ill is secondary - it IS
what Python does). There is no special use of '^' as a shortcut for
'return' (as in Smalltalk's ubiquitous "^self") - one writes "return self".

Please reconsider the "def f() [classmethod]:" construct. Instead of
invoking a special punctuation character, it uses context and placement,
with familiar old []'s, to infuse the declaration of a function with special
characteristics. If this causes def lines to run longer than one line,
perhaps the same rule that allows an unmatched "(" to carry over multiple
lines without requiring "\" continuation markers could be used for unmatched
"["s, as in:

def f() [ staticmethod,
synchronized,
alphabetized,
supersized,
returns('d') ]:
"If I'd wanted mucilage, I'dve ordered mucilage." - Humphrey Bogart, "All
Through the Night"
If I'd wanted to write in Java, I'dve written in Java.

Keep Python Beautiful.
-- Paul

Jul 18 '05 #12

P: n/a
Istvan Albert <ia*****@mailblocks.com>
wrote on Thu, 05 Aug 2004 16:58:07 -0400:
Mark 'Kamikaze' Hughes wrote:
class foo:
def introduceNewFeature(self, someArgument, anotherArgument): [synchronized, types="o,i,i"]
pass # whatever

Those who need argument type-checking should
go to Guido and talk to him about it. Piggybacking
this in as decorators makes everybody lose.


They have talked to him about it. It's been talked to death. One of
the major groups pushing for decorators are PyObjC users, who need it to
make the interface vaguely tolerable.

Also consider web services, which need metadata to access Python with
anything but raw strings. That metadata can be stored in an XML file or
something, but it's best if it's *right there* on the function def.

This is not an in-Python type-checking mechanism, but a mechanism for
attaching additional information to functions, mostly so they can
interact with things that are not Python.
3) A large proportion of Python programmers are also Java programmers,
and won't object to the @-syntax.

yay. love is in the air.


I have no idea what you were trying to say there.

--
<a href="http://kuoi.asui.uidaho.edu/~kamikaze/"> Mark Hughes </a>
"Virtues foster one another; so too, vices.
Bad English kills trees, consumes energy, and befouls the Earth.
Good English renews it." -The Underground Grammarian, v1n2
Jul 18 '05 #13

P: n/a
On Thu, 5 Aug 2004 09:45:40 -0400, Christopher T King
<sq******@WPI.EDU> wrote:

I think much of the problem in coming up with a universally acceptable
decorator solution is that we're trying to kill too many birds with one
stone. I believe the decorator problem can be seperated into at least
three distinct needs:


I don't pretend to have an adequate grasp of the technical issues:

But I certainly find the argument you make in the portion oif the post
that followed from the above well constructed and (intuitively)
convincing.

Though I am also intuiting that the fact that I happen to do so may
not have a major influence on the debate ;).
Art
Jul 18 '05 #14

P: n/a
> This is backwards compatible (Python <= 2.3 raise
SyntaxError), and looks much nicer than @.


"Almost" anything looks better than the @ syntax.
If @ gets implemented, there goes the whole easily-readable plug for
Python.
We might as all go learn Perl.

While everyone is fussing around on the syntax of decorators, I think
they should change the name as well (although I don't have a
reasonable alternative yet). Decorator is the least program-like term
I've ever heard of. :)
Jul 18 '05 #15

P: n/a
"Tony C" <ca*******@yahoo.com> wrote in message
news:8d**************************@posting.google.c om...
This is backwards compatible (Python <= 2.3 raise
SyntaxError), and looks much nicer than @.


"Almost" anything looks better than the @ syntax.
If @ gets implemented, there goes the whole easily-readable plug for
Python.
We might as all go learn Perl.

While everyone is fussing around on the syntax of decorators, I think
they should change the name as well (although I don't have a
reasonable alternative yet). Decorator is the least program-like term
I've ever heard of. :)


Talk to the Gang of Four about that. Decorator is straight out of the
Design Patterns book.

-- Paul
Jul 18 '05 #16

P: n/a
Christopher T King wrote:
Another (perhaps better) method of declaring metadata has been previously
proposed, that of function attributes:

def foo(a,b,c):
.accepts = (int,int,list)
.author = 'Chris King'


How about

def foo(a, b, c):
foo.accepts = (int, int, list)
foo.author = 'Chris King'

--
Yawar Amin
Jul 18 '05 #17

P: n/a
On Sat, 07 Aug 2004 16:28:11 +0600, Yawar Amin <ya********@gmail.com> wrote:
How about

def foo(a, b, c):
foo.accepts = (int, int, list)
foo.author = 'Chris King'


How would you express foo=classmethod(foo) in this syntax? Far better to have
one flexible tool in the toolbox than a host of little, less functional tools.
Jul 18 '05 #18

P: n/a

"Anthony Baxter" <an***********@gmail.com> wrote in message
news:ma**************************************@pyth on.org...
On Sat, 07 Aug 2004 16:28:11 +0600, Yawar Amin <ya********@gmail.com> wrote:
How about

def foo(a, b, c):
foo.accepts = (int, int, list)
foo.author = 'Chris King'


How would you express foo=classmethod(foo) in this syntax? Far better to

have one flexible tool in the toolbox than a host of little, less functional

tools.

Well, You could add a decorate method with the following signature to
functions:

func.decorate(*decorators, **attributes)

Then use:

def foo(a, b, c):
"foo can decorate itself, from the inside"
foo.decorate(abstract, synchronized, classmethod,
accepts=(int,int,int), author='Chris King')
...
...


Jul 18 '05 #19

P: n/a

"Sean Ross" <sr***@connectmail.carleton.ca> wrote in message
news:O%*********************@news20.bellglobal.com ...
def foo(a, b, c):
"foo can decorate itself, from the inside"
foo.decorate(abstract, synchronized, classmethod,
accepts=(int,int,int), author='Chris King')
...
...


Actually, nevermind: foo's going to call decorate every time it's called.
Not good. Also it doesn't work with multi|generic method schemes, nor with
really_long_function_or_method_names().

Jul 18 '05 #20

P: n/a
Paul McGuire wrote:

Please reconsider the "def f() [classmethod]:" construct. Instead of
invoking a special punctuation character, it uses context and placement,
with familiar old []'s, to infuse the declaration of a function with special
characteristics. If this causes def lines to run longer than one line,
perhaps the same rule that allows an unmatched "(" to carry over multiple
lines without requiring "\" continuation markers could be used for unmatched
"["s, as in:

def f() [ staticmethod,
synchronized,
alphabetized,
supersized,
returns('d') ]:
"If I'd wanted mucilage, I'dve ordered mucilage." - Humphrey Bogart, "All
Through the Night"
If I'd wanted to write in Java, I'dve written in Java.

Keep Python Beautiful.


Full ACK!

But I fear that without a formal "voting" Python will go the pragmatic
way - that is, keep @ as it's already implemented.

So what would be the most effective way to notify the developers that
(I'm guessing) 90% of the Python community dislike the @ syntax and want
an other?

Reinhold

--
Wenn eine Linuxdistribution so wenig brauchbare Software wie Windows
mitbrächte, wäre das bedauerlich. Was bei Windows der Umfang eines
"kompletten Betriebssystems" ist, nennt man bei Linux eine Rescuedisk.
-- David Kastrup in de.comp.os.unix.linux.misc
Jul 18 '05 #21

P: n/a
On Sat, 07 Aug 2004 20:15:01 +0200, Reinhold Birkenfeld
<re************************@wolke7.net> wrote:
But I fear that without a formal "voting" Python will go the pragmatic
way - that is, keep @ as it's already implemented.
Sorry - but would "formal voting" be a good way to design a language?
Based on various languages that have gone through a committee type
process, I'd have to say "god no".
So what would be the most effective way to notify the developers that
(I'm guessing) 90% of the Python community dislike the @ syntax and want
an other?


As I've said (repeatedly) - this isn't a popularity contest. The point is to
produce the best technical result. If you have a better solution, put together
a case for it, and convince Guido.

I'd also question how you can be so sure that "90% of the community
dislike it" -
over on python-dev, there's been quite a number of people who've actually
tried the syntax, and found it to be quite good. This includes me -
when I first saw it, I recoiled, but after using it, I find it pretty good.
Please, please - download a2. Try the decorator syntax out (or look at
test_decorators, or the hopefully-finished-with-the-rewrite-soon PEP318
(which I'll also post here) for examples.

Anthony
Jul 18 '05 #22

P: n/a
On Sun, 8 Aug 2004 06:40:32 +1000, Anthony Baxter
<an***********@gmail.com> wrote:
On Sat, 07 Aug 2004 20:15:01 +0200, Reinhold Birkenfeld
<re************************@wolke7.net> wrote:
But I fear that without a formal "voting" Python will go the pragmatic
way - that is, keep @ as it's already implemented.

As I've said (repeatedly) - this isn't a popularity contest. The point
is to
produce the best technical result. If you have a better solution, put
together
a case for it, and convince Guido wrong list for this
Please, please - download a2. Try the decorator syntax out (or look at
test_decorators, or the hopefully-finished-with-the-rewrite-soon PEP318
(which I'll also post here) for examples. There is no need to use a new syntax to appriciate it,it's only a syntax
we can read it.
Anthony


If it has been simple to estabilish the use of the docstring (which I
don't use waiting (in vain ?) for a literate python) now
this story of decorators has nothing to do with a decoration of the
language.It's like we must learn a new way of reading our
favourite way of coding,and some of us don't understand why we must do
it,as this feature is not for making new things.
All in all:if it's only a new way of writing things they can already be
written,it's very normal every typer/reader want to express
his/her preference,mainly because wants to use it.
Every language has a sensual side,Python (and Ruby eheh) beats them all
and this battle shows the pride of loving it.

Paolino
--
.....lotta dura per la verdura

Jul 18 '05 #23

P: n/a
Yawar Amin wrote:
How about

def foo(a, b, c):
foo.accepts = (int, int, list)
foo.author = 'Chris King'


That already has a different meaning: Function foo sets those attributes
on itself each time it is called. They should be set once, before the
function is called.

$ python2.3
def foo(a, b, c): .... foo.accepts = (int, int, list)
.... foo.author = 'Chris King'
.... foo.author Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: 'function' object has no attribute 'author' foo(1,2,3)
foo.author

'Chris King'

--
Hallvard
Jul 18 '05 #24

This discussion thread is closed

Replies have been disabled for this discussion.