2003-06-09 00:04:58 -04:00
|
|
|
|
PEP: 318
|
2004-08-06 12:02:42 -04:00
|
|
|
|
Title: Decorators for Functions and Methods
|
2003-06-09 00:04:58 -04:00
|
|
|
|
Version: $Revision$
|
|
|
|
|
Last-Modified: $Date$
|
2008-12-29 22:48:55 -05:00
|
|
|
|
Author: Kevin D. Smith <Kevin.Smith@theMorgue.org>, Jim J. Jewett, Skip Montanaro, Anthony Baxter
|
2005-01-29 13:24:59 -05:00
|
|
|
|
Status: Final
|
2003-06-09 00:04:58 -04:00
|
|
|
|
Type: Standards Track
|
2004-03-23 11:41:17 -05:00
|
|
|
|
Content-Type: text/x-rst
|
2003-06-09 00:04:58 -04:00
|
|
|
|
Created: 05-Jun-2003
|
|
|
|
|
Python-Version: 2.4
|
2004-09-01 11:02:22 -04:00
|
|
|
|
Post-History: 09-Jun-2003, 10-Jun-2003, 27-Feb-2004, 23-Mar-2004, 30-Aug-2004,
|
2022-03-09 11:04:44 -05:00
|
|
|
|
02-Sep-2004
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
|
|
|
|
|
2004-08-19 11:36:14 -04:00
|
|
|
|
WarningWarningWarning
|
|
|
|
|
=====================
|
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
This document is meant to describe the decorator syntax and the
|
2004-09-01 19:40:12 -04:00
|
|
|
|
process that resulted in the decisions that were made. It does not
|
|
|
|
|
attempt to cover the huge number of potential alternative syntaxes,
|
|
|
|
|
nor is it an attempt to exhaustively list all the positives and
|
2004-09-01 11:02:22 -04:00
|
|
|
|
negatives of each form.
|
2004-08-30 11:01:09 -04:00
|
|
|
|
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
2003-06-09 00:04:58 -04:00
|
|
|
|
Abstract
|
2004-03-23 11:41:17 -05:00
|
|
|
|
========
|
2004-03-25 16:45:58 -05:00
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
The current method for transforming functions and methods (for instance,
|
|
|
|
|
declaring them as a class or static method) is awkward and can lead to
|
|
|
|
|
code that is difficult to understand. Ideally, these transformations
|
|
|
|
|
should be made at the same point in the code where the declaration
|
|
|
|
|
itself is made. This PEP introduces new syntax for transformations of a
|
|
|
|
|
function or method declaration.
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Motivation
|
2004-03-23 11:41:17 -05:00
|
|
|
|
==========
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
The current method of applying a transformation to a function or method
|
2004-09-01 11:44:33 -04:00
|
|
|
|
places the actual transformation after the function body. For large
|
2004-09-01 11:02:22 -04:00
|
|
|
|
functions this separates a key component of the function's behavior from
|
|
|
|
|
the definition of the rest of the function's external interface. For
|
|
|
|
|
example::
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
def foo(self):
|
|
|
|
|
perform method operation
|
|
|
|
|
foo = classmethod(foo)
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
This becomes less readable with longer methods. It also seems less
|
2004-09-01 11:02:22 -04:00
|
|
|
|
than pythonic to name the function three times for what is conceptually
|
|
|
|
|
a single declaration. A solution to this problem is to move the
|
|
|
|
|
transformation of the method closer to the method's own declaration.
|
2007-05-02 03:14:15 -04:00
|
|
|
|
The intent of the new syntax is to replace ::
|
2003-06-10 00:29:48 -04:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
def foo(cls):
|
|
|
|
|
pass
|
|
|
|
|
foo = synchronized(lock)(foo)
|
|
|
|
|
foo = classmethod(foo)
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
with an alternative that places the decoration in the function's
|
|
|
|
|
declaration::
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-08-05 23:36:09 -04:00
|
|
|
|
@classmethod
|
|
|
|
|
@synchronized(lock)
|
|
|
|
|
def foo(cls):
|
2004-03-23 11:41:17 -05:00
|
|
|
|
pass
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
Modifying classes in this fashion is also possible, though the benefits
|
|
|
|
|
are not as immediately apparent. Almost certainly, anything which could
|
|
|
|
|
be done with class decorators could be done using metaclasses, but
|
|
|
|
|
using metaclasses is sufficiently obscure that there is some attraction
|
|
|
|
|
to having an easier way to make simple modifications to classes. For
|
|
|
|
|
Python 2.4, only function/method decorators are being added.
|
2004-03-25 16:45:58 -05:00
|
|
|
|
|
2022-01-21 06:03:51 -05:00
|
|
|
|
:pep:`3129` proposes to add class decorators as of Python 2.6.
|
2007-05-02 03:14:15 -04:00
|
|
|
|
|
2004-03-30 08:39:21 -05:00
|
|
|
|
|
2004-08-24 14:56:00 -04:00
|
|
|
|
Why Is This So Hard?
|
|
|
|
|
--------------------
|
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
Two decorators (``classmethod()`` and ``staticmethod()``) have been
|
|
|
|
|
available in Python since version 2.2. It's been assumed since
|
2004-08-24 14:56:00 -04:00
|
|
|
|
approximately that time that some syntactic support for them would
|
|
|
|
|
eventually be added to the language. Given this assumption, one might
|
2004-09-01 11:02:22 -04:00
|
|
|
|
wonder why it's been so difficult to arrive at a consensus. Discussions
|
|
|
|
|
have raged off-and-on at times in both comp.lang.python and the
|
|
|
|
|
python-dev mailing list about how best to implement function decorators.
|
|
|
|
|
There is no one clear reason why this should be so, but a few problems
|
2004-09-01 11:44:33 -04:00
|
|
|
|
seem to be most divisive.
|
2004-08-24 14:56:00 -04:00
|
|
|
|
|
|
|
|
|
* Disagreement about where the "declaration of intent" belongs.
|
2004-09-01 11:02:22 -04:00
|
|
|
|
Almost everyone agrees that decorating/transforming a function at the
|
|
|
|
|
end of its definition is suboptimal. Beyond that there seems to be no
|
|
|
|
|
clear consensus where to place this information.
|
2004-08-24 14:56:00 -04:00
|
|
|
|
|
|
|
|
|
* Syntactic constraints. Python is a syntactically simple language
|
|
|
|
|
with fairly strong constraints on what can and can't be done without
|
|
|
|
|
"messing things up" (both visually and with regards to the language
|
|
|
|
|
parser). There's no obvious way to structure this information so
|
|
|
|
|
that people new to the concept will think, "Oh yeah, I know what
|
2004-09-01 11:02:22 -04:00
|
|
|
|
you're doing." The best that seems possible is to keep new users from
|
|
|
|
|
creating a wildly incorrect mental model of what the syntax means.
|
2004-08-24 14:56:00 -04:00
|
|
|
|
|
|
|
|
|
* Overall unfamiliarity with the concept. For people who have a
|
|
|
|
|
passing acquaintance with algebra (or even basic arithmetic) or have
|
|
|
|
|
used at least one other programming language, much of Python is
|
|
|
|
|
intuitive. Very few people will have had any experience with the
|
|
|
|
|
decorator concept before encountering it in Python. There's just no
|
|
|
|
|
strong preexisting meme that captures the concept.
|
|
|
|
|
|
2004-08-30 09:16:56 -04:00
|
|
|
|
* Syntax discussions in general appear to cause more contention than
|
2004-09-01 11:02:22 -04:00
|
|
|
|
almost anything else. Readers are pointed to the ternary operator
|
2022-01-21 06:03:51 -05:00
|
|
|
|
discussions that were associated with :pep:`308` for another example of
|
2004-08-30 09:16:56 -04:00
|
|
|
|
this.
|
2004-08-24 14:56:00 -04:00
|
|
|
|
|
2004-08-30 11:01:09 -04:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
Background
|
|
|
|
|
==========
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
There is general agreement that syntactic support is desirable to
|
|
|
|
|
the current state of affairs. Guido mentioned `syntactic support
|
|
|
|
|
for decorators`_ in his DevDay keynote presentation at the `10th
|
|
|
|
|
Python Conference`_, though `he later said`_ it was only one of
|
|
|
|
|
several extensions he proposed there "semi-jokingly". `Michael Hudson
|
|
|
|
|
raised the topic`_ on ``python-dev`` shortly after the conference,
|
2004-08-19 11:36:14 -04:00
|
|
|
|
attributing the initial bracketed syntax to an earlier proposal on
|
2004-03-25 16:45:58 -05:00
|
|
|
|
``comp.lang.python`` by `Gareth McCaughan`_.
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-03-30 08:39:21 -05:00
|
|
|
|
.. _syntactic support for decorators:
|
|
|
|
|
http://www.python.org/doc/essays/ppt/python10/py10keynote.pdf
|
|
|
|
|
.. _10th python conference:
|
|
|
|
|
http://www.python.org/workshops/2002-02/
|
|
|
|
|
.. _michael hudson raised the topic:
|
2017-06-11 15:02:39 -04:00
|
|
|
|
https://mail.python.org/pipermail/python-dev/2002-February/020005.html
|
2004-03-30 08:39:21 -05:00
|
|
|
|
.. _he later said:
|
2017-06-11 15:02:39 -04:00
|
|
|
|
https://mail.python.org/pipermail/python-dev/2002-February/020017.html
|
2004-03-30 08:39:21 -05:00
|
|
|
|
.. _gareth mccaughan:
|
|
|
|
|
http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=slrna40k88.2h9o.Gareth.McCaughan%40g.local
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-03-25 16:45:58 -05:00
|
|
|
|
Class decorations seem like an obvious next step because class
|
2004-09-01 11:02:22 -04:00
|
|
|
|
definition and function definition are syntactically similar,
|
|
|
|
|
however Guido remains unconvinced, and class decorators will almost
|
|
|
|
|
certainly not be in Python 2.4.
|
|
|
|
|
|
|
|
|
|
The discussion continued on and off on python-dev from February
|
|
|
|
|
2002 through July 2004. Hundreds and hundreds of posts were made,
|
|
|
|
|
with people proposing many possible syntax variations. Guido took
|
|
|
|
|
a list of proposals to `EuroPython 2004`_, where a discussion took
|
2004-09-01 19:40:12 -04:00
|
|
|
|
place. Subsequent to this, he decided that we'd have the `Java-style`_
|
|
|
|
|
@decorator syntax, and this appeared for the first time in 2.4a2.
|
|
|
|
|
Barry Warsaw named this the 'pie-decorator' syntax, in honor of the
|
2016-07-11 11:14:08 -04:00
|
|
|
|
Pie-thon Parrot shootout which occurred around the same time as
|
2004-09-01 19:40:12 -04:00
|
|
|
|
the decorator syntax, and because the @ looks a little like a pie.
|
|
|
|
|
Guido `outlined his case`_ on Python-dev, including `this piece`_
|
2004-09-01 11:02:22 -04:00
|
|
|
|
on some of the (many) rejected forms.
|
2004-08-05 23:36:09 -04:00
|
|
|
|
|
2004-08-06 10:27:38 -04:00
|
|
|
|
.. _EuroPython 2004:
|
2004-08-05 23:36:09 -04:00
|
|
|
|
http://www.python.org/doc/essays/ppt/euro2004/euro2004.pdf
|
2004-08-06 10:27:38 -04:00
|
|
|
|
.. _outlined his case:
|
2017-06-11 15:02:39 -04:00
|
|
|
|
https://mail.python.org/pipermail/python-dev/2004-August/author.html
|
2004-08-06 10:27:38 -04:00
|
|
|
|
.. _this piece:
|
2017-06-11 15:02:39 -04:00
|
|
|
|
https://mail.python.org/pipermail/python-dev/2004-August/046672.html
|
2004-08-19 21:14:23 -04:00
|
|
|
|
.. _Java-style:
|
2004-08-19 11:36:14 -04:00
|
|
|
|
http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html
|
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
|
2004-08-19 11:36:14 -04:00
|
|
|
|
On the name 'Decorator'
|
|
|
|
|
=======================
|
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
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 its use in the `GoF book`_. The name 'decorator'
|
|
|
|
|
probably owes more to its use in the compiler area -- a syntax tree is
|
|
|
|
|
walked and annotated. It's quite possible that a better name may turn
|
|
|
|
|
up.
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
.. _GoF book:
|
2020-05-24 04:21:56 -04:00
|
|
|
|
https://web.archive.org/web/20031204182047/http://patterndigest.com/patterns/Decorator.html
|
2004-03-30 08:39:21 -05:00
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
Design Goals
|
|
|
|
|
============
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
The new syntax should
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
* work for arbitrary wrappers, including user-defined callables and
|
2004-08-24 01:50:01 -04:00
|
|
|
|
the existing builtins ``classmethod()`` and ``staticmethod()``. This
|
|
|
|
|
requirement also means that a decorator syntax must support passing
|
|
|
|
|
arguments to the wrapper constructor
|
2004-08-19 21:14:23 -04:00
|
|
|
|
|
|
|
|
|
* work with multiple wrappers per definition
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
* make it obvious what is happening; at the very least it should be
|
|
|
|
|
obvious that new users can safely ignore it when writing their own
|
|
|
|
|
code
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-08-24 01:50:01 -04:00
|
|
|
|
* be a syntax "that ... [is] easy to remember once explained"
|
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
* not make future extensions more difficult
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
* be easy to type; programs that use it are expected to use it very
|
|
|
|
|
frequently
|
2003-06-10 00:29:48 -04:00
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
* not make it more difficult to scan through code quickly. It should
|
2004-09-01 11:02:22 -04:00
|
|
|
|
still be easy to search for all definitions, a particular definition,
|
|
|
|
|
or the arguments that a function accepts
|
2003-06-10 00:29:48 -04:00
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
* not needlessly complicate secondary support tools such as
|
|
|
|
|
language-sensitive editors and other "`toy parser tools out
|
|
|
|
|
there`_"
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-08-24 01:50:01 -04:00
|
|
|
|
* allow future compilers to optimize for decorators. With the hope of
|
|
|
|
|
a JIT compiler for Python coming into existence at some point this
|
2004-09-01 11:02:22 -04:00
|
|
|
|
tends to require the syntax for decorators to come before the function
|
|
|
|
|
definition
|
2004-08-24 01:50:01 -04:00
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
* move from the end of the function, where it's currently hidden, to
|
|
|
|
|
the front where it is more `in your face`_
|
2003-06-10 00:29:48 -04:00
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
Andrew Kuchling has links to a bunch of the discussions about
|
|
|
|
|
motivations and use cases `in his blog`_. Particularly notable is `Jim
|
|
|
|
|
Huginin's list of use cases`_.
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
2004-03-30 08:39:21 -05:00
|
|
|
|
.. _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
|
2004-08-19 21:14:23 -04:00
|
|
|
|
.. _in your face:
|
2017-06-11 15:02:39 -04:00
|
|
|
|
https://mail.python.org/pipermail/python-dev/2004-August/047112.html
|
2004-08-06 10:27:38 -04:00
|
|
|
|
.. _in his blog:
|
2004-08-05 23:36:09 -04:00
|
|
|
|
http://www.amk.ca/diary/archives/cat_python.html#003255
|
2004-08-19 11:36:14 -04:00
|
|
|
|
.. _Jim Huginin's list of use cases:
|
2017-06-11 15:02:39 -04:00
|
|
|
|
https://mail.python.org/pipermail/python-dev/2004-April/044132.html
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
|
2004-08-19 11:36:14 -04:00
|
|
|
|
Current Syntax
|
|
|
|
|
==============
|
2003-06-10 00:29:48 -04:00
|
|
|
|
|
2004-08-05 23:36:09 -04:00
|
|
|
|
The current syntax for function decorators as implemented in Python
|
|
|
|
|
2.4a2 is::
|
|
|
|
|
|
|
|
|
|
@dec2
|
|
|
|
|
@dec1
|
|
|
|
|
def func(arg1, arg2, ...):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
This is equivalent to::
|
2004-02-28 14:09:44 -05:00
|
|
|
|
|
2004-08-05 23:36:09 -04:00
|
|
|
|
def func(arg1, arg2, ...):
|
2004-03-23 11:41:17 -05:00
|
|
|
|
pass
|
2004-08-05 23:36:09 -04:00
|
|
|
|
func = dec2(dec1(func))
|
2004-02-28 14:09:44 -05:00
|
|
|
|
|
2004-08-05 23:53:20 -04:00
|
|
|
|
without the intermediate assignment to the variable ``func``. The
|
2004-09-01 11:02:22 -04:00
|
|
|
|
decorators are near the function declaration. The @ sign makes it clear
|
|
|
|
|
that something new is going on here.
|
2004-02-28 14:09:44 -05:00
|
|
|
|
|
2004-09-14 03:34:23 -04:00
|
|
|
|
The rationale for the `order of application`_ (bottom to top) is that it
|
|
|
|
|
matches the usual order for function-application. In mathematics,
|
|
|
|
|
composition of functions (g o f)(x) translates to g(f(x)). In Python,
|
|
|
|
|
``@g @f def foo()`` translates to ``foo=g(f(foo)``.
|
2017-03-24 17:11:33 -04:00
|
|
|
|
|
2004-09-14 03:34:23 -04:00
|
|
|
|
.. _order of application:
|
2017-06-11 15:02:39 -04:00
|
|
|
|
https://mail.python.org/pipermail/python-dev/2004-September/048874.html
|
2004-09-14 03:34:23 -04:00
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
The decorator statement is limited in what it can accept -- arbitrary
|
|
|
|
|
expressions will not work. Guido preferred this because of a `gut
|
|
|
|
|
feeling`_.
|
2004-03-25 16:45:58 -05:00
|
|
|
|
|
2004-08-06 10:27:38 -04:00
|
|
|
|
.. _gut feeling:
|
2017-06-11 15:02:39 -04:00
|
|
|
|
https://mail.python.org/pipermail/python-dev/2004-August/046711.html
|
2004-03-25 16:45:58 -05:00
|
|
|
|
|
2004-09-14 03:34:23 -04:00
|
|
|
|
The current syntax also allows decorator declarations to call a
|
|
|
|
|
function that returns a decorator::
|
|
|
|
|
|
|
|
|
|
@decomaker(argA, argB, ...)
|
|
|
|
|
def func(arg1, arg2, ...):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
This is equivalent to::
|
|
|
|
|
|
|
|
|
|
func = decomaker(argA, argB, ...)(func)
|
|
|
|
|
|
|
|
|
|
The rationale for having a function that returns a decorator is that
|
|
|
|
|
the part after the @ sign can be considered to be an expression
|
|
|
|
|
(though syntactically restricted to just a function), and whatever
|
|
|
|
|
that expression returns is called. See `declaration arguments`_.
|
|
|
|
|
|
|
|
|
|
.. _declaration arguments:
|
2017-06-11 15:02:39 -04:00
|
|
|
|
https://mail.python.org/pipermail/python-dev/2004-September/048874.html
|
2004-09-14 03:34:23 -04:00
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
|
2004-08-19 11:36:14 -04:00
|
|
|
|
Syntax Alternatives
|
|
|
|
|
===================
|
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
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
|
2004-08-30 09:16:56 -04:00
|
|
|
|
act of madness, and produce a completely unwieldy PEP.
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
.. _a large number:
|
2004-08-19 11:36:14 -04:00
|
|
|
|
http://www.python.org/moin/PythonDecorators
|
2004-08-19 21:14:23 -04:00
|
|
|
|
.. _each possible syntax:
|
2004-08-19 11:36:14 -04:00
|
|
|
|
http://ucsu.colorado.edu/~bethard/py/decorators-output.py
|
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
|
2004-08-19 11:36:14 -04:00
|
|
|
|
Decorator Location
|
|
|
|
|
------------------
|
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
The first syntax point is the location of the decorators. For the
|
2004-08-19 11:36:14 -04:00
|
|
|
|
following examples, we use the @syntax used in 2.4a2.
|
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
Decorators before the def statement are the first alternative, and the
|
|
|
|
|
syntax used in 2.4a2::
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def foo(arg1,arg2):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
@accepts(int,int)
|
|
|
|
|
@returns(float)
|
|
|
|
|
def bar(low,high):
|
|
|
|
|
pass
|
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
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
|
2004-09-01 19:40:12 -04:00
|
|
|
|
has an effect on a following line. The syntax available in 2.4a3
|
2004-09-01 11:02:22 -04:00
|
|
|
|
requires one decorator per line (in a2, multiple decorators could be
|
2007-05-02 03:14:15 -04:00
|
|
|
|
specified on the same line), and the final decision for 2.4 final stayed
|
|
|
|
|
one decorator per line.
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
2004-09-01 11:44:33 -04:00
|
|
|
|
People also complained that the syntax quickly got unwieldy when
|
2004-08-24 01:50:01 -04:00
|
|
|
|
multiple decorators were used. The point was made, though, that the
|
|
|
|
|
chances of a large number of decorators being used on a single function
|
|
|
|
|
were small and thus this was not a large worry.
|
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
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.
|
2004-08-24 01:50:01 -04:00
|
|
|
|
|
2004-09-01 11:44:33 -04:00
|
|
|
|
Another advantage is that a prefix to the function definition fits
|
2004-09-01 11:02:22 -04:00
|
|
|
|
the idea of knowing about a change to the semantics of the code before
|
2004-09-01 11:44:33 -04:00
|
|
|
|
the code itself, thus you know how to interpret the code's semantics
|
2004-08-24 01:50:01 -04:00
|
|
|
|
properly without having to go back and change your initial perceptions
|
|
|
|
|
if the syntax did not come before the function definition.
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
2004-08-30 09:16:56 -04:00
|
|
|
|
Guido decided `he preferred`_ having the decorators on the line before
|
2004-09-01 11:02:22 -04:00
|
|
|
|
the 'def', because it was felt that a long argument list would mean that
|
|
|
|
|
the decorators would be 'hidden'
|
2004-08-30 09:16:56 -04:00
|
|
|
|
|
|
|
|
|
.. _he preferred:
|
2017-06-11 15:02:39 -04:00
|
|
|
|
https://mail.python.org/pipermail/python-dev/2004-March/043756.html
|
2004-08-30 09:16:56 -04:00
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
The second form is the decorators between the def and the function name,
|
|
|
|
|
or the function name and the argument list::
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
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,
|
2004-09-01 11:02:22 -04:00
|
|
|
|
more serious, objection is that in the case of multiple decorators, the
|
|
|
|
|
syntax would be extremely unwieldy.
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
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::
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
|
|
|
|
def foo(arg1,arg2) @classmethod:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def bar(low,high) @accepts(int,int),@returns(float):
|
|
|
|
|
pass
|
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
Guido `summarized the arguments`_ against this form (many of which also
|
|
|
|
|
apply to the previous form) as:
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
|
|
|
|
- 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
|
|
|
|
|
|
2004-08-30 09:16:56 -04:00
|
|
|
|
.. _summarized the arguments:
|
2017-06-11 15:02:39 -04:00
|
|
|
|
https://mail.python.org/pipermail/python-dev/2004-August/047112.html
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
2004-09-01 11:44:33 -04:00
|
|
|
|
The next form is that the decorator syntax goes inside the method body at
|
2016-05-03 04:35:10 -04:00
|
|
|
|
the start, in the same place that docstrings currently live::
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
|
|
|
|
def foo(arg1,arg2):
|
|
|
|
|
@classmethod
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def bar(low,high):
|
|
|
|
|
@accepts(int,int)
|
|
|
|
|
@returns(float)
|
|
|
|
|
pass
|
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
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.
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
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. ::
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
|
|
|
|
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
|
2004-09-01 11:02:22 -04:00
|
|
|
|
undecorated methods. In addition, a decorated method's body would start
|
|
|
|
|
three indent levels in.
|
2004-08-19 21:14:23 -04:00
|
|
|
|
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
|
|
|
|
Syntax forms
|
|
|
|
|
------------
|
|
|
|
|
|
2004-08-30 09:16:56 -04:00
|
|
|
|
* ``@decorator``::
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def foo(arg1,arg2):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
@accepts(int,int)
|
|
|
|
|
@returns(float)
|
|
|
|
|
def bar(low,high):
|
|
|
|
|
pass
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
The major objections against this syntax are that the @ symbol is
|
|
|
|
|
not currently used in Python (and is used in both IPython and Leo),
|
2004-09-01 11:02:22 -04:00
|
|
|
|
and that the @ symbol is not meaningful. Another objection is that
|
2004-08-30 09:16:56 -04:00
|
|
|
|
this "wastes" a currently unused character (from a limited set) on
|
|
|
|
|
something that is not perceived as a major use.
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
2004-08-30 09:16:56 -04:00
|
|
|
|
* ``|decorator``::
|
|
|
|
|
|
|
|
|
|
|classmethod
|
|
|
|
|
def foo(arg1,arg2):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|accepts(int,int)
|
|
|
|
|
|returns(float)
|
|
|
|
|
def bar(low,high):
|
|
|
|
|
pass
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
This is a variant on the @decorator syntax -- it has the advantage
|
|
|
|
|
that it does not break IPython and Leo. Its major disadvantage
|
2004-09-01 11:02:22 -04:00
|
|
|
|
compared to the @syntax is that the | symbol looks like both a capital
|
|
|
|
|
I and a lowercase l.
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
2004-08-30 09:16:56 -04:00
|
|
|
|
* list syntax::
|
|
|
|
|
|
|
|
|
|
[classmethod]
|
|
|
|
|
def foo(arg1,arg2):
|
|
|
|
|
pass
|
|
|
|
|
|
2004-09-01 19:40:12 -04:00
|
|
|
|
[accepts(int,int), returns(float)]
|
|
|
|
|
def bar(low,high):
|
|
|
|
|
pass
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
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.
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
2004-08-30 09:16:56 -04:00
|
|
|
|
* list syntax using other brackets (``<...>``, ``[[...]]``, ...)::
|
|
|
|
|
|
|
|
|
|
<classmethod>
|
|
|
|
|
def foo(arg1,arg2):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
<accepts(int,int), returns(float)>
|
2004-09-01 19:40:12 -04:00
|
|
|
|
def bar(low,high):
|
|
|
|
|
pass
|
2004-08-30 09:16:56 -04:00
|
|
|
|
|
|
|
|
|
None of these alternatives gained much traction. The alternatives
|
|
|
|
|
which involve square brackets only serve to make it obvious that the
|
|
|
|
|
decorator construct is not a list. They do nothing to make parsing any
|
|
|
|
|
easier. The '<...>' alternative presents parsing problems because '<'
|
|
|
|
|
and '>' already parse as un-paired. They present a further parsing
|
|
|
|
|
ambiguity because a right angle bracket might be a greater than symbol
|
|
|
|
|
instead of a closer for the decorators.
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
* ``decorate()``
|
2004-08-19 11:36:14 -04:00
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
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
|
2004-08-19 21:14:23 -04:00
|
|
|
|
implementations of functions that did this. Guido was pretty firmly
|
|
|
|
|
against this -- with no new syntax, the magicness of a function like
|
2004-08-30 09:16:56 -04:00
|
|
|
|
this is extremely high:
|
2004-08-05 23:36:09 -04:00
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
Using functions with "action-at-a-distance" through sys.settraceback
|
|
|
|
|
may be okay for an obscure feature that can't be had any other
|
|
|
|
|
way yet doesn't merit changes to the language, but that's not
|
|
|
|
|
the situation for decorators. The widely held view here is that
|
|
|
|
|
decorators need to be added as a syntactic feature to avoid the
|
|
|
|
|
problems with the postfix notation used in 2.2 and 2.3. Decorators
|
|
|
|
|
are slated to be an important new language feature and their
|
|
|
|
|
design needs to be forward-looking, not constrained by what can be
|
|
|
|
|
implemented in 2.3.
|
2004-08-05 23:36:09 -04:00
|
|
|
|
|
2004-08-30 11:01:09 -04:00
|
|
|
|
* _`new keyword (and block)`
|
2004-08-05 23:53:20 -04:00
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
This idea was the consensus alternate from comp.lang.python (more
|
|
|
|
|
on this in `Community Consensus`_ below.) Robert Brewer wrote up a
|
|
|
|
|
detailed `J2 proposal`_ document outlining the arguments in favor of
|
|
|
|
|
this form. The initial issues with this form are:
|
2004-08-05 23:53:20 -04:00
|
|
|
|
|
2004-08-30 11:01:09 -04:00
|
|
|
|
- It requires a new keyword, and therefore a ``from __future__
|
|
|
|
|
import decorators`` statement.
|
2004-08-05 23:53:20 -04:00
|
|
|
|
|
2004-08-30 11:01:09 -04:00
|
|
|
|
- The choice of keyword is contentious. However ``using`` emerged
|
|
|
|
|
as the consensus choice, and is used in the proposal and
|
|
|
|
|
implementation.
|
|
|
|
|
|
|
|
|
|
- The keyword/block form produces something that looks like a normal
|
|
|
|
|
code block, but isn't. Attempts to use statements in this block
|
2004-08-30 12:00:06 -04:00
|
|
|
|
will cause a syntax error, which may confuse users.
|
2004-08-30 11:01:09 -04:00
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
A few days later, Guido `rejected the proposal`_ on two main grounds,
|
|
|
|
|
firstly:
|
|
|
|
|
|
|
|
|
|
... the syntactic form of an indented block strongly
|
|
|
|
|
suggests that its contents should be a sequence of statements, but
|
|
|
|
|
in fact it is not -- only expressions are allowed, and there is an
|
|
|
|
|
implicit "collecting" of these expressions going on until they can
|
|
|
|
|
be applied to the subsequent function definition. ...
|
|
|
|
|
|
|
|
|
|
and secondly:
|
|
|
|
|
|
|
|
|
|
... the keyword starting the line that heads a block
|
|
|
|
|
draws a lot of attention to it. This is true for "if", "while",
|
|
|
|
|
"for", "try", "def" and "class". But the "using" keyword (or any
|
|
|
|
|
other keyword in its place) doesn't deserve that attention; the
|
|
|
|
|
emphasis should be on the decorator or decorators inside the suite,
|
|
|
|
|
since those are the important modifiers to the function definition
|
|
|
|
|
that follows. ...
|
|
|
|
|
|
|
|
|
|
Readers are invited to read `the full response`_.
|
2004-08-30 09:16:56 -04:00
|
|
|
|
|
2004-08-30 11:01:09 -04:00
|
|
|
|
.. _J2 proposal:
|
|
|
|
|
http://www.aminus.org/rbre/python/pydec.html
|
2004-08-30 09:16:56 -04:00
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
.. _rejected the proposal:
|
2017-06-11 15:02:39 -04:00
|
|
|
|
https://mail.python.org/pipermail/python-dev/2004-September/048518.html
|
2004-09-01 11:02:22 -04:00
|
|
|
|
|
|
|
|
|
.. _the full response:
|
2017-06-11 15:02:39 -04:00
|
|
|
|
https://mail.python.org/pipermail/python-dev/2004-September/048518.html
|
2004-09-01 11:02:22 -04:00
|
|
|
|
|
2004-09-01 19:40:12 -04:00
|
|
|
|
* Other forms
|
2004-09-01 11:02:22 -04:00
|
|
|
|
|
|
|
|
|
There are plenty of other variants and proposals on `the wiki page`_.
|
2004-08-30 09:16:56 -04:00
|
|
|
|
|
|
|
|
|
.. _the wiki page:
|
2017-09-16 05:08:44 -04:00
|
|
|
|
https://wiki.python.org/moin/PythonDecoratorProposals
|
2004-08-30 09:16:56 -04:00
|
|
|
|
|
2004-08-30 11:01:09 -04:00
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
Why @?
|
2004-08-05 23:36:09 -04:00
|
|
|
|
------
|
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
There is some history in Java using @ initially as a marker in `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 there is no possibility of such code
|
|
|
|
|
being parsed by an earlier version of Python, leading to possibly subtle
|
|
|
|
|
semantic bugs. It also means that ambiguity of what is a decorator
|
2004-09-01 11:44:33 -04:00
|
|
|
|
and what isn't is removed. That said, @ is still a fairly arbitrary
|
2004-09-01 11:02:22 -04:00
|
|
|
|
choice. Some have suggested using | instead.
|
2004-08-05 23:36:09 -04:00
|
|
|
|
|
|
|
|
|
For syntax options which use a list-like syntax (no matter where it
|
|
|
|
|
appears) to specify the decorators a few alternatives were proposed:
|
2004-09-01 11:02:22 -04:00
|
|
|
|
``[|...|]``, ``*[...]*``, and ``<...>``.
|
2004-08-30 09:16:56 -04:00
|
|
|
|
|
2004-08-06 10:27:38 -04:00
|
|
|
|
.. _Javadoc comments:
|
2004-08-05 23:36:09 -04:00
|
|
|
|
http://java.sun.com/j2se/javadoc/writingdoccomments/
|
2004-08-19 21:14:23 -04:00
|
|
|
|
.. _annotations:
|
2004-08-19 11:36:14 -04:00
|
|
|
|
http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html
|
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
|
2004-08-30 09:16:56 -04:00
|
|
|
|
Current Implementation, History
|
|
|
|
|
===============================
|
2003-06-10 00:29:48 -04:00
|
|
|
|
|
2004-08-30 09:16:56 -04:00
|
|
|
|
Guido asked for a volunteer to implement his preferred syntax, and Mark
|
2004-09-01 19:40:12 -04:00
|
|
|
|
Russell stepped up and posted a `patch`_ to SF. This new syntax was
|
2004-09-01 11:02:22 -04:00
|
|
|
|
available in 2.4a2. ::
|
2003-06-10 00:29:48 -04:00
|
|
|
|
|
2004-08-05 23:36:09 -04:00
|
|
|
|
@dec2
|
|
|
|
|
@dec1
|
|
|
|
|
def func(arg1, arg2, ...):
|
2004-03-23 11:41:17 -05:00
|
|
|
|
pass
|
2003-06-10 00:29:48 -04:00
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
This is equivalent to::
|
2003-07-29 11:31:13 -04:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
def func(arg1, arg2, ...):
|
|
|
|
|
pass
|
|
|
|
|
func = dec2(dec1(func))
|
2004-02-28 14:09:44 -05:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
though without the intermediate creation of a variable named ``func``.
|
2003-07-29 11:31:13 -04:00
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
The version implemented in 2.4a2 allowed multiple ``@decorator`` clauses
|
|
|
|
|
on a single line. In 2.4a3, this was tightened up to only allowing one
|
|
|
|
|
decorator per line.
|
|
|
|
|
|
2004-08-05 23:36:09 -04:00
|
|
|
|
A `previous patch`_ from Michael Hudson which implements the
|
|
|
|
|
list-after-def syntax is also still kicking around.
|
|
|
|
|
|
2018-07-21 19:57:17 -04:00
|
|
|
|
.. _patch: https://bugs.python.org/issue979728
|
2004-08-05 23:36:09 -04:00
|
|
|
|
.. _previous patch: http://starship.python.net/crew/mwh/hacks/meth-syntax-sugar-3.diff
|
2003-07-29 11:31:13 -04:00
|
|
|
|
|
2004-08-30 11:01:09 -04:00
|
|
|
|
After 2.4a2 was released, in response to community reaction, Guido
|
|
|
|
|
stated that he'd re-examine a community proposal, if the community
|
2004-08-30 09:16:56 -04:00
|
|
|
|
could come up with a community consensus, a decent proposal, and an
|
2004-08-30 11:01:09 -04:00
|
|
|
|
implementation. After an amazing number of posts, collecting a vast
|
|
|
|
|
number of alternatives in the `Python wiki`_, a community consensus
|
2004-09-01 11:02:22 -04:00
|
|
|
|
emerged (below). Guido `subsequently rejected`_ this alternate form,
|
|
|
|
|
but added:
|
|
|
|
|
|
|
|
|
|
In Python 2.4a3 (to be released this Thursday), everything remains
|
|
|
|
|
as currently in CVS. For 2.4b1, I will consider a change of @ to
|
|
|
|
|
some other single character, even though I think that @ has the
|
|
|
|
|
advantage of being the same character used by a similar feature
|
|
|
|
|
in Java. It's been argued that it's not quite the same, since @
|
|
|
|
|
in Java is used for attributes that don't change semantics. But
|
|
|
|
|
Python's dynamic nature makes that its syntactic elements never mean
|
|
|
|
|
quite the same thing as similar constructs in other languages, and
|
|
|
|
|
there is definitely significant overlap. Regarding the impact on
|
|
|
|
|
3rd party tools: IPython's author doesn't think there's going to be
|
|
|
|
|
much impact; Leo's author has said that Leo will survive (although
|
|
|
|
|
it will cause him and his users some transitional pain). I actually
|
|
|
|
|
expect that picking a character that's already used elsewhere in
|
|
|
|
|
Python's syntax might be harder for external tools to adapt to,
|
|
|
|
|
since parsing will have to be more subtle in that case. But I'm
|
|
|
|
|
frankly undecided, so there's some wiggle room here. I don't want
|
|
|
|
|
to consider further syntactic alternatives at this point: the buck
|
|
|
|
|
has to stop at some point, everyone has had their say, and the show
|
|
|
|
|
must go on.
|
2004-08-30 09:16:56 -04:00
|
|
|
|
|
|
|
|
|
.. _Python wiki:
|
2020-06-11 22:18:51 -04:00
|
|
|
|
http://wiki.python.org/moin/PythonDecorators
|
2004-09-01 11:02:22 -04:00
|
|
|
|
.. _subsequently rejected:
|
2017-06-11 15:02:39 -04:00
|
|
|
|
https://mail.python.org/pipermail/python-dev/2004-September/048518.html
|
2004-08-30 11:01:09 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Community Consensus
|
|
|
|
|
-------------------
|
|
|
|
|
|
2017-03-24 17:11:33 -04:00
|
|
|
|
This section documents the rejected J2 syntax, and is included for
|
2004-09-03 05:32:50 -04:00
|
|
|
|
historical completeness.
|
2004-09-01 11:02:22 -04:00
|
|
|
|
|
|
|
|
|
The consensus that emerged on comp.lang.python was the proposed J2
|
|
|
|
|
syntax (the "J2" was how it was referenced on the PythonDecorators wiki
|
|
|
|
|
page): the new keyword ``using`` prefixing a block of decorators before
|
|
|
|
|
the ``def`` statement. For example::
|
2004-08-30 11:01:09 -04:00
|
|
|
|
|
|
|
|
|
using:
|
|
|
|
|
classmethod
|
|
|
|
|
synchronized(lock)
|
|
|
|
|
def func(cls):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
The main arguments for this syntax fall under the "readability counts"
|
|
|
|
|
doctrine. In brief, they are:
|
|
|
|
|
|
|
|
|
|
* A suite is better than multiple @lines. The ``using`` keyword and
|
|
|
|
|
block transforms the single-block ``def`` statement into a
|
|
|
|
|
multiple-block compound construct, akin to try/finally and others.
|
|
|
|
|
|
|
|
|
|
* A keyword is better than punctuation for a new token. A keyword
|
|
|
|
|
matches the existing use of tokens. No new token category is
|
|
|
|
|
necessary. A keyword distinguishes Python decorators from Java
|
|
|
|
|
annotations and .Net attributes, which are significantly different
|
|
|
|
|
beasts.
|
|
|
|
|
|
|
|
|
|
Robert Brewer wrote a `detailed proposal`_ for this form, and Michael
|
|
|
|
|
Sparks produced `a patch`_.
|
|
|
|
|
|
2004-08-30 09:16:56 -04:00
|
|
|
|
.. _detailed proposal:
|
|
|
|
|
http://www.aminus.org/rbre/python/pydec.html
|
2004-09-01 19:40:12 -04:00
|
|
|
|
.. _a patch:
|
2018-07-21 19:57:17 -04:00
|
|
|
|
https://bugs.python.org/issue1013835
|
2004-08-30 09:16:56 -04:00
|
|
|
|
|
2004-09-01 11:02:22 -04:00
|
|
|
|
As noted previously, Guido rejected this form, outlining his problems
|
|
|
|
|
with it in `a message`_ to python-dev and comp.lang.python.
|
|
|
|
|
|
|
|
|
|
.. _a message:
|
2017-06-11 15:02:39 -04:00
|
|
|
|
https://mail.python.org/pipermail/python-dev/2004-September/048518.html
|
2004-09-01 11:02:22 -04:00
|
|
|
|
|
2004-03-30 08:39:21 -05:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
Examples
|
|
|
|
|
========
|
2003-06-10 00:29:48 -04:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
Much of the discussion on ``comp.lang.python`` and the ``python-dev``
|
2004-03-25 16:45:58 -05:00
|
|
|
|
mailing list focuses on the use of decorators as a cleaner way to use
|
2004-09-01 11:02:22 -04:00
|
|
|
|
the ``staticmethod()`` and ``classmethod()`` builtins. This capability
|
|
|
|
|
is much more powerful than that. This section presents some examples of
|
|
|
|
|
use.
|
2003-06-10 00:29:48 -04:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
1. Define a function to be executed at exit. Note that the function
|
2004-08-19 21:14:23 -04:00
|
|
|
|
isn't actually "wrapped" in the usual sense. ::
|
2004-03-23 11:41:17 -05:00
|
|
|
|
|
2004-03-30 08:39:21 -05:00
|
|
|
|
def onexit(f):
|
|
|
|
|
import atexit
|
|
|
|
|
atexit.register(f)
|
|
|
|
|
return f
|
2004-03-23 11:41:17 -05:00
|
|
|
|
|
2004-08-05 23:53:20 -04:00
|
|
|
|
@onexit
|
|
|
|
|
def func():
|
2004-03-30 08:39:21 -05:00
|
|
|
|
...
|
2004-03-23 11:41:17 -05:00
|
|
|
|
|
2004-08-30 09:16:56 -04:00
|
|
|
|
Note that this example is probably not suitable for real usage, but
|
|
|
|
|
is for example purposes only.
|
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
2. Define a class with a singleton instance. Note that once the class
|
2004-09-01 11:02:22 -04:00
|
|
|
|
disappears enterprising programmers would have to be more creative to
|
|
|
|
|
create more instances. (From Shane Hathaway on ``python-dev``.) ::
|
2004-03-23 11:41:17 -05:00
|
|
|
|
|
2004-03-30 08:39:21 -05:00
|
|
|
|
def singleton(cls):
|
2004-04-08 17:14:34 -04:00
|
|
|
|
instances = {}
|
|
|
|
|
def getinstance():
|
|
|
|
|
if cls not in instances:
|
|
|
|
|
instances[cls] = cls()
|
|
|
|
|
return instances[cls]
|
|
|
|
|
return getinstance
|
2003-06-10 00:29:48 -04:00
|
|
|
|
|
2004-08-05 23:53:20 -04:00
|
|
|
|
@singleton
|
|
|
|
|
class MyClass:
|
2004-03-30 08:39:21 -05:00
|
|
|
|
...
|
2003-06-10 00:29:48 -04:00
|
|
|
|
|
2004-03-31 13:19:22 -05:00
|
|
|
|
3. Add attributes to a function. (Based on an example posted by
|
2004-08-19 21:14:23 -04:00
|
|
|
|
Anders Munch on ``python-dev``.) ::
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-03-31 13:19:22 -05:00
|
|
|
|
def attrs(**kwds):
|
2004-03-30 08:39:21 -05:00
|
|
|
|
def decorate(f):
|
|
|
|
|
for k in kwds:
|
|
|
|
|
setattr(f, k, kwds[k])
|
|
|
|
|
return f
|
|
|
|
|
return decorate
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-08-05 23:53:20 -04:00
|
|
|
|
@attrs(versionadded="2.2",
|
|
|
|
|
author="Guido van Rossum")
|
|
|
|
|
def mymethod(f):
|
2004-03-30 08:39:21 -05:00
|
|
|
|
...
|
2004-03-23 11:41:17 -05:00
|
|
|
|
|
2004-09-01 19:40:12 -04:00
|
|
|
|
4. Enforce function argument and return types. Note that this
|
2004-08-30 09:16:56 -04:00
|
|
|
|
copies the func_name attribute from the old to the new function.
|
|
|
|
|
func_name was made writable in Python 2.4a3::
|
2004-03-30 08:39:21 -05:00
|
|
|
|
|
|
|
|
|
def accepts(*types):
|
|
|
|
|
def check_accepts(f):
|
|
|
|
|
assert len(types) == f.func_code.co_argcount
|
|
|
|
|
def new_f(*args, **kwds):
|
|
|
|
|
for (a, t) in zip(args, types):
|
|
|
|
|
assert isinstance(a, t), \
|
|
|
|
|
"arg %r does not match %s" % (a,t)
|
|
|
|
|
return f(*args, **kwds)
|
2004-08-30 09:16:56 -04:00
|
|
|
|
new_f.func_name = f.func_name
|
2004-03-30 08:39:21 -05:00
|
|
|
|
return new_f
|
|
|
|
|
return check_accepts
|
|
|
|
|
|
|
|
|
|
def returns(rtype):
|
|
|
|
|
def check_returns(f):
|
|
|
|
|
def new_f(*args, **kwds):
|
|
|
|
|
result = f(*args, **kwds)
|
|
|
|
|
assert isinstance(result, rtype), \
|
|
|
|
|
"return value %r does not match %s" % (result,rtype)
|
|
|
|
|
return result
|
2004-08-30 09:16:56 -04:00
|
|
|
|
new_f.func_name = f.func_name
|
2004-03-30 08:39:21 -05:00
|
|
|
|
return new_f
|
|
|
|
|
return check_returns
|
|
|
|
|
|
2004-08-05 23:53:20 -04:00
|
|
|
|
@accepts(int, (int,float))
|
|
|
|
|
@returns((int,float))
|
|
|
|
|
def func(arg1, arg2):
|
2004-03-30 08:39:21 -05:00
|
|
|
|
return arg1 * arg2
|
2004-03-23 11:41:17 -05:00
|
|
|
|
|
2004-03-25 16:45:58 -05:00
|
|
|
|
5. Declare that a class implements a particular (set of) interface(s).
|
|
|
|
|
This is from a posting by Bob Ippolito on ``python-dev`` based on
|
2004-08-19 21:14:23 -04:00
|
|
|
|
experience with `PyProtocols`_. ::
|
2004-03-25 16:45:58 -05:00
|
|
|
|
|
2004-03-30 08:39:21 -05:00
|
|
|
|
def provides(*interfaces):
|
|
|
|
|
"""
|
|
|
|
|
An actual, working, implementation of provides for
|
|
|
|
|
the current implementation of PyProtocols. Not
|
|
|
|
|
particularly important for the PEP text.
|
|
|
|
|
"""
|
|
|
|
|
def provides(typ):
|
|
|
|
|
declareImplementation(typ, instancesProvide=interfaces)
|
|
|
|
|
return typ
|
|
|
|
|
return provides
|
2004-03-25 16:45:58 -05:00
|
|
|
|
|
2004-03-30 08:39:21 -05:00
|
|
|
|
class IBar(Interface):
|
|
|
|
|
"""Declare something about IBar here"""
|
2004-03-25 16:45:58 -05:00
|
|
|
|
|
2004-08-05 23:53:20 -04:00
|
|
|
|
@provides(IBar)
|
|
|
|
|
class Foo(object):
|
2004-03-30 08:39:21 -05:00
|
|
|
|
"""Implement something here..."""
|
2004-03-25 16:45:58 -05:00
|
|
|
|
|
2004-08-19 21:14:23 -04:00
|
|
|
|
.. _PyProtocols: http://peak.telecommunity.com/PyProtocols.html
|
|
|
|
|
|
2004-08-05 23:53:20 -04:00
|
|
|
|
Of course, all these examples are possible today, though without
|
2004-03-23 11:41:17 -05:00
|
|
|
|
syntactic support.
|
|
|
|
|
|
2004-03-30 08:39:21 -05:00
|
|
|
|
|
2007-05-02 03:14:15 -04:00
|
|
|
|
(No longer) Open Issues
|
|
|
|
|
=======================
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-03-25 16:45:58 -05:00
|
|
|
|
1. It's not yet certain that class decorators will be incorporated
|
2004-09-01 11:02:22 -04:00
|
|
|
|
into the language at a future point. Guido expressed skepticism about
|
2004-03-25 16:45:58 -05:00
|
|
|
|
the concept, but various people have made some `strong arguments`_
|
2004-08-19 21:14:23 -04:00
|
|
|
|
(search for ``PEP 318 -- posting draft``) on their behalf in
|
2004-09-01 19:40:12 -04:00
|
|
|
|
``python-dev``. It's exceedingly unlikely that class decorators
|
2004-09-01 11:02:22 -04:00
|
|
|
|
will be in Python 2.4.
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-03-30 08:39:21 -05:00
|
|
|
|
.. _strong arguments:
|
2017-06-11 15:02:39 -04:00
|
|
|
|
https://mail.python.org/pipermail/python-dev/2004-March/thread.html
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2022-01-21 06:03:51 -05:00
|
|
|
|
:pep:`3129` proposes to add class decorators as of Python 2.6.
|
2007-05-02 03:14:15 -04:00
|
|
|
|
|
2004-09-01 19:40:12 -04:00
|
|
|
|
2. The choice of the ``@`` character will be re-examined before
|
2004-09-01 11:02:22 -04:00
|
|
|
|
Python 2.4b1.
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2007-05-02 03:14:15 -04:00
|
|
|
|
In the end, the ``@`` character was kept.
|
|
|
|
|
|
|
|
|
|
|
2003-06-09 00:04:58 -04:00
|
|
|
|
Copyright
|
2004-03-23 11:41:17 -05:00
|
|
|
|
=========
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
This document has been placed in the public domain.
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
|
|
|
|
|
2004-04-04 12:31:42 -04:00
|
|
|
|
..
|
|
|
|
|
Local Variables:
|
|
|
|
|
mode: indented-text
|
|
|
|
|
indent-tabs-mode: nil
|
|
|
|
|
sentence-end-double-space: t
|
|
|
|
|
fill-column: 70
|
|
|
|
|
End:
|