checking in work-in-progress. this is by no means finished -

I will attack it some more this weekend and attempt to finish it.
Please feel free to fill out any bits you think I've missed.
See the WarningWarningWarning section at the top.
This commit is contained in:
Anthony Baxter 2004-08-19 15:36:14 +00:00
parent c5f6f6b146
commit 9f2f16ef45
1 changed files with 224 additions and 15 deletions

View File

@ -4,7 +4,8 @@ Version: $Revision$
Last-Modified: $Date$ Last-Modified: $Date$
Author: Kevin D. Smith <Kevin.Smith@theMorgue.org>, Author: Kevin D. Smith <Kevin.Smith@theMorgue.org>,
Jim Jewett <jimjjewett@users.sourceforge.net>, Jim Jewett <jimjjewett@users.sourceforge.net>,
Skip Montanaro <skip@pobox.com> Skip Montanaro <skip@pobox.com>,
Anthony Baxter <anthony@python.org>
Status: Draft Status: Draft
Type: Standards Track Type: Standards Track
Content-Type: text/x-rst Content-Type: text/x-rst
@ -13,14 +14,25 @@ Python-Version: 2.4
Post-History: 09-Jun-2003, 10-Jun-2003, 27-Feb-2004, 23-Mar-2004 Post-History: 09-Jun-2003, 10-Jun-2003, 27-Feb-2004, 23-Mar-2004
WarningWarningWarning
=====================
This is not yet complete. This is still a work-in-progress. Feedback
to anthony. Please note that the point of this PEP is _not_ to provide
an open-slather of plusses and minuses for each syntax, but is instead
to justify the choice made. If, in 2.4a3, the syntax is changed, the
PEP will be updated to match this, complete with the arguments for the
change.
Abstract Abstract
======== ========
The current method for declaring class and static methods is awkward The current method for transforming functions and methods (for instance,
and can lead to code that is difficult to understand. Ideally, these declaring them as a class or static method) is awkward and can lead to
transformations should be made at the same point in the code where the code that is difficult to understand. Ideally, these transformations
declaration itself is made. This PEP introduces new syntax for should be made at the same point in the code where the declaration
transformations of a declaration. itself is made. This PEP introduces new syntax for transformations of a
function or method declaration.
Motivation Motivation
@ -61,8 +73,8 @@ benefits are not as immediately apparent. Almost certainly, anything
which could be done with class decorators could be done using which could be done with class decorators could be done using
metaclasses, but using metaclasses is sufficiently obscure that there metaclasses, but using metaclasses is sufficiently obscure that there
is some attraction to having an easier way to make simple is some attraction to having an easier way to make simple
modifications to classes. For Python 2.4, only function decorators modifications to classes. For Python 2.4, only function/method
are being added. decorators are being added.
Background Background
@ -74,7 +86,7 @@ decorators`_ in his DevDay keynote presentation at the `10th Python
Conference`_, though `he later said`_ it was only one of several Conference`_, though `he later said`_ it was only one of several
extensions he proposed there "semi-jokingly". `Michael Hudson raised extensions he proposed there "semi-jokingly". `Michael Hudson raised
the topic`_ on ``python-dev`` shortly after the conference, the topic`_ on ``python-dev`` shortly after the conference,
attributing the bracketed syntax to an earlier proposal on attributing the initial bracketed syntax to an earlier proposal on
``comp.lang.python`` by `Gareth McCaughan`_. ``comp.lang.python`` by `Gareth McCaughan`_.
.. _syntactic support for decorators: .. _syntactic support for decorators:
@ -92,10 +104,10 @@ Class decorations seem like an obvious next step because class
definition and function definition are syntactically similar. definition and function definition are syntactically similar.
The discussion continued on and off on python-dev from February 2002 The discussion continued on and off on python-dev from February 2002
through July 2004. Many hundreds of posts were made, with people through July 2004. Hundreds and hundreds of posts were made, with people
proposing many possible syntax variations. Guido took a list of proposing many possible syntax variations. Guido took a list of
proposals to `EuroPython 2004`_, where a discussion took place. proposals to `EuroPython 2004`_, where a discussion took place.
Subsequent to this, he decided that for 2.4a2 we'd have the Java-style Subsequent to this, he decided that for 2.4a2 we'd have the `Java-style`_
@decorator syntax. Barry Warsaw named this the 'pie-decorator' @decorator syntax. Barry Warsaw named this the 'pie-decorator'
syntax, in honor of the Pie-thon Parrot shootout which was announced syntax, in honor of the Pie-thon Parrot shootout which was announced
about the same time as the decorator syntax, and because the @ looks a about the same time as the decorator syntax, and because the @ looks a
@ -111,6 +123,21 @@ including `this piece`_ on the various rejected forms.
.. _this piece: .. _this piece:
http://mail.python.org/pipermail/python-dev/2004-August/046672.html http://mail.python.org/pipermail/python-dev/2004-August/046672.html
.. Java-style:
http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html
On the name 'Decorator'
=======================
There's been a number of complaints about the choice of the name
'decorator' for this feature. The major one is that the name is
not consistent with it's use in the `GoF book`_. The name 'decorator'
probably owes more to it's use in the compiler area - a syntax tree
is walked and annotated. It's quite possible that a better name may
turn up.
.. GoF book:
http://patterndigest.com/patterns/Decorator.html
Design Goals Design Goals
============ ============
@ -139,17 +166,27 @@ The new syntax should
language-sensitive editors and other "`toy parser tools out language-sensitive editors and other "`toy parser tools out
there`_" there`_"
* move from the end of the function, where it's currently hidden, to
the front where it is more `in your face`_
.. _toy parser tools out there: .. _toy parser tools out there:
http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=mailman.1010809396.32158.python-list%40python.org http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=mailman.1010809396.32158.python-list%40python.org
.. in your face:
http://mail.python.org/pipermail/python-dev/2004-August/047112.html
Andrew Kuchling has links to a bunch of the discussions about motivations Andrew Kuchling has links to a bunch of the discussions about motivations
`in his blog`_. and use cases `in his blog`_. Particularly notable is `Jim Huginin's list
of use cases`_.
.. _in his blog: .. _in his blog:
http://www.amk.ca/diary/archives/cat_python.html#003255 http://www.amk.ca/diary/archives/cat_python.html#003255
Proposed Syntax .. _Jim Huginin's list of use cases:
=============== http://mail.python.org/pipermail/python-dev/2004-April/044132.html
Current Syntax
==============
The current syntax for function decorators as implemented in Python The current syntax for function decorators as implemented in Python
2.4a2 is:: 2.4a2 is::
@ -175,10 +212,178 @@ expressions will not work. Guido preferred this because of a `gut feeling`_
.. _gut feeling: .. _gut feeling:
http://mail.python.org/pipermail/python-dev/2004-August/046711.html http://mail.python.org/pipermail/python-dev/2004-August/046711.html
Syntax Alternatives
===================
There have been `a large number`_ of different syntaxes proposed - rather
than attempting to work through these individual syntaxes, it's worthwhile
to break the syntax discussion down into a number of areas. Attempting to
discuss `each possible syntax`_ individually would be an act of madness,
and produce a completely unwieldly PEP.
.. a large number:
http://www.python.org/moin/PythonDecorators
.. each possible syntax:
http://ucsu.colorado.edu/~bethard/py/decorators-output.py
Decorator Location
------------------
The first syntax point is the location of the decorators. For the
following examples, we use the @syntax used in 2.4a2.
Decorators before the def statement are the first alternative,
and the syntax used in 2.4a2::
@classmethod
def foo(arg1,arg2):
pass
@accepts(int,int)
@returns(float)
def bar(low,high):
pass
There have been a number of objections raised to this location -
the primary one is that it's the first real Python case where a
line of code has a result on a following line. The syntax that
will be in 2.4a3 will also require one decorator per line (in a2,
multiple decorators can be specified on the same line).
Some of the advantages of this form are that the decorators live
outside the method body - they are obviously executed at the time
the function is defined
The second form is the decorators between the def and the function
name, or the function name and the argument list::
def @classmethod foo(arg1,arg2):
pass
def @accepts(int,int),@returns(float) bar(low,high):
pass
def foo @classmethod (arg1,arg2):
pass
def bar @accepts(int,int),@returns(float) (low,high):
pass
There are a couple of objections to this form.
The first is that it breaks easily 'greppability' of the source - you
can no longer search for 'def foo(' and find the definition of the
function. The second, more serious, objection is that in the case
of multiple decorators, the syntax would be extremely unwieldy.
The next form, which has had a number of strong proponents, is to
have the decorators between the argument list and the trailing ``:``
in the 'def' line::
def foo(arg1,arg2) @classmethod:
pass
def bar(low,high) @accepts(int,int),@returns(float):
pass
Guido `summarised the arguments`_ against this form (many of which
also apply to the previous form) as:
- it hides crucial information (e.g. that it is a static method)
after the signature, where it is easily missed
- it's easy to miss the transition between a long argument list and a
long decorator list
- it's cumbersome to cut and paste a decorator list for reuse, because
it starts and ends in the middle of a line
.. summarised the arguments:
http://mail.python.org/pipermail/python-dev/2004-August/047112.html
The next form is that the decorator syntax go inside the method
body at the start, in the same place that docstrings currently
live:
def foo(arg1,arg2):
@classmethod
pass
def bar(low,high):
@accepts(int,int)
@returns(float)
pass
The primary objection to this form is that it requires "peeking inside"
the method body to determine the decorators. In addition, even though
the code is inside the method body, it is not executed when the method
is run. Guido felt that docstrings were not a good counter-example, and
that it was quite possible that a 'docstring' decorator could help move
the docstring to outside the function body.
The final form is a new block that encloses the method's code. For this
example, we'll use a 'decorate' keyword, as it makes no sense with the
@syntax.
decorate:
classmethod
def foo(arg1,arg2):
pass
decorate:
accepts(int,int)
returns(float)
def bar(low,high):
pass
This form would result in inconsistent indentation for decorated and
undecorated methods. In addition, a decorated method's body would start
three indent levels in.
Syntax forms
------------
@decorator
The major objections against this syntax are that the @ symbol
is not currently used in Python (and is used in both IPython and
Leo), that the @ symbol is not meaningful,
|decorator
This is a variant on the @decorator syntax - it has the advantage
that it does not break IPython and Leo. It's major disadvantage
compared to the @syntax is that the | symbol looks like both a
capital I and a lowercase l.
* list syntax
The major objection to the list syntax is that it's currently
meaningful (when used in the form before the method). It's also
lacking any indication that the expression is a decorator.
* list syntax using other brackets ( <...>, [[...]], ... )
* decorate()
The decorate() proposal was that no new syntax be implemented -
instead a magic function that used introspection to manipulate
the following function. Both Jp Calderone and Philip Eby produced
implementations of functions that did this. Guido was pretty firmly
against this - with no new syntax, the magicness of a function like
this is extremely high.
* new keyword (and block)
Alternate Proposals Alternate Proposals
=================== ===================
The text in this section will be integrated into the previous section.
They're here for hysterical raisins for now.
Several other syntaxes have been proposed:: Several other syntaxes have been proposed::
def func(arg1, arg2, ...) as dec1, dec2, ...: def func(arg1, arg2, ...) as dec1, dec2, ...:
@ -300,7 +505,8 @@ Why @?
------ ------
There is some history in Java using @ initially as a marker in There is some history in Java using @ initially as a marker in
`Javadoc comments`_ and later in ... mumble mumble ... The fact that `Javadoc comments`_ and later in Java 1.5 for `annotations`_,
which are similar to Python decorators. The fact that
@ was previously unused as a token in Python also means it's clear @ was previously unused as a token in Python also means it's clear
there is no possibility of such code being parsed by an earlier there is no possibility of such code being parsed by an earlier
version of Python, leading to possibly subtle semantic bugs. That version of Python, leading to possibly subtle semantic bugs. That
@ -320,6 +526,9 @@ greater than symbol instead of a closer for the decorators.
.. _Javadoc comments: .. _Javadoc comments:
http://java.sun.com/j2se/javadoc/writingdoccomments/ http://java.sun.com/j2se/javadoc/writingdoccomments/
.. annotations:
http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html
Current Implementation Current Implementation
====================== ======================