469,955 Members | 2,576 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,955 developers. It's quick & easy.

Proposed improved decorator syntax


I'm revising my vote.

Thanks for the responses.

I vote against:

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

Pros:
- Allows arbitrary functions to be applied as decorators.

Cons:
- Places decorator metadata before the function (in contrast with docstrings).
- Hides function name.
- @ symbols are ugly.
- @ symbols are a particular hack for creating function metadata.
- More such hacks may be needed in the future.
- @ can be used to store metadata, but in a convoluted way:
@name('Value') works, if function 'name' is defined (imports must be used
for large projects); however the metadata name actually stored may be
different than 'name' (ie no symmetry, no ease of use).
- @ will be used for metadata, if no other solution is provided.

Recognize that we're *really* trying to create function metadata. A more
flexible solution is to make a metadata dictionary be part of function and
class definitions. Then 'decorator' simply becomes one name among many
different metadata names.

I vote for:

---------------------------------------------------------------------
Proposed Syntax
---------------------------------------------------------------------

class foo:
def introduceNewFeature(self, someArgument, anotherArgument):
.decorate = [synchronized]
.accepts = (int, int)
.author = 'Chris King'
pass # whatever

Use introduceNewFeature.__meta__ to access the metadata dict.
The .accepts meta-datum calls isinstance() for each argument.
Use 'object' for arguments that can be any type.

Pros:
- Readable.
- No ugly @ symbols.
- Metadata is placed after the function name.
- .decorate is semantically superior to @.
- Similar to existing Python syntax (equals sign and dots).
- Allows metadata to be created and read (symmetrically, easily).
- Allows arbitrary functions to be applied as decorators.
- Code is ordered correctly (function declaration before docstring and
metadata).

Cons:
- Name conflicts between builtin metadata names (eg 'decorate') and
user metadata names (eg 'decorate').

Solutions to Name Conflicts:
- Name conflicts are a small problem if the set of Python special
metadata names is kept small and well documented (eg '.decorate'
and '.accepts' can be documented as 'metadata keywords', to be
avoided).
- The paranoid can prefix metadata names with underscores.
- Alternatively, .__decorate__ and .__accepts__ can be used.
- Alternatively, {'decorate': [synchronized], 'accepts': (int, int)}
can be used as the first line of metadata, which is interpreted
as a 'Python special metadata dict'.

---------------------------------------------------------------------
Conclusion
---------------------------------------------------------------------

Either attack the full problem of metadata, or don't.

@ is a hack. @ looks ugly. @ is a particular solution for the general
problem domain of metadata. @ is not clear to the uninitiated. @ is
counter-intuitively present before the docstring. @name('Value') is
can be used to store metadata, but lacks ease of use and symmetry.

Finally, @ does not appear to follow the tradition of Python. It is a
very specialized extension statement, and at least deserves a descriptive
identifier in the code like 'decorate'.

Please don't stay silent on this issue. Speak out!

We should really have a public vote. I doubt the @ sign will be approved
if 99% of Python users oppose it.

- Connelly
Jul 18 '05 #1
5 1124
wrote in news:ma**************************************@pyth on.org in
comp.lang.python:
class foo:
def introduceNewFeature(self, someArgument, anotherArgument):
.decorate = [synchronized]
.accepts = (int, int)
.author = 'Chris King'
pass # whatever


AIUI it is intended that prefix '.' will be used at some point
with a 'with'/'using' keyword:

class Foo:
def f( self ):
with self:
.member = value

But since we can have function's in function's and we already
have "special" member functions (__init__ etc):

class Foo:

def method( self ):

def __decorate__( func ):
synchronized( func )

__accepts__ = (int, int)
__author__ = "whoever"

pass

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 18 '05 #2
On 6 Aug 2004, Rob Williscroft wrote:
wrote in news:ma**************************************@pyth on.org in
comp.lang.python:
class foo:
def introduceNewFeature(self, someArgument, anotherArgument):
.decorate = [synchronized]
.accepts = (int, int)
.author = 'Chris King'
pass # whatever


AIUI it is intended that prefix '.' will be used at some point
with a 'with'/'using' keyword:

class Foo:
def f( self ):
with self:
.member = value


Which makes it all the more intuitive (def is acting similar to a with
block).

Jul 18 '05 #3
Christopher T King wrote in news:Pine.LNX.4.44.0408060917330.30087-100000
@ccc6.wpi.edu in comp.lang.python:
On 6 Aug 2004, Rob Williscroft wrote:
wrote in news:ma**************************************@pyth on.org in
comp.lang.python:
> class foo:
> def introduceNewFeature(self, someArgument, anotherArgument):
> .decorate = [synchronized]
> .accepts = (int, int)
> .author = 'Chris King'
> pass # whatever
>
>


AIUI it is intended that prefix '.' will be used at some point
with a 'with'/'using' keyword:

class Foo:
def f( self ):
with self:
.member = value


Which makes it all the more intuitive (def is acting similar to a with
block).


Intuitivly I would then expect .decorate to apply to self not to f.

But that's on a sample of 1 person's intuition :).

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 18 '05 #4
barnesc wrote:
class foo:
def introduceNewFeature(self, someArgument, anotherArgument):
.decorate = [synchronized]
.accepts = (int, int)
.author = 'Chris King'
pass # whatever
I like it better than the current syntax, but I'm troubled by stuff
after the ':' which is executed before the function.
It _looks_ like it is executed inside the function.

Also, the scoping is a bit strange:

def bar(self, baz):
.decorate = [baz]
pass # whatever

The decorator looks like it refers to the function parameter, but it
doesn't: the parameter has no value when the decorator is set. Though I
guess a simple fix in this case is simply to forbid decorators to use
names that occur as function parameters.

Rob Williscroft wrote:
But since we can have function's in function's and we already
have "special" member functions (__init__ etc):

class Foo:

def method( self ):

def __decorate__( func ):
synchronized( func )

__accepts__ = (int, int)
__author__ = "whoever"

pass


Same problem, only worse. The def statements of special member
functions are executed while the class body is executed, just like defs
of normal functions. OTOH, your special functions inside functions must
be executed once before the function is called.

--
Hallvard
Jul 18 '05 #5
On 08 Aug 2004 02:51:12 +0200, Hallvard B Furuseth
<h.**********@usit.uio.no> wrote:
barnesc wrote:
class foo:
def introduceNewFeature(self, someArgument, anotherArgument):
.decorate = [synchronized]
.accepts = (int, int)
.author = 'Chris King'
pass # whatever


I like it better than the current syntax, but I'm troubled by stuff
after the ':' which is executed before the function.
It _looks_ like it is executed inside the function.


This was Guido's reason for rejecting all forms that put the decorator
syntax inside the function block. They're _not_ part of the function's
code.
Jul 18 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

14 posts views Thread by Sandy Norton | last post: by
24 posts views Thread by Steven Bethard | last post: by
11 posts views Thread by Ville Vainio | last post: by
7 posts views Thread by Steven Bethard | last post: by
41 posts views Thread by John Marshall | last post: by
17 posts views Thread by Jim Jewett | last post: by
22 posts views Thread by Ron_Adam | last post: by
108 posts views Thread by Bryan Olson | last post: by
13 posts views Thread by Lad | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.