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$
|
2004-03-30 08:39:21 -05:00
|
|
|
|
Author: Kevin D. Smith <Kevin.Smith@theMorgue.org>,
|
2004-03-23 11:41:17 -05:00
|
|
|
|
Jim Jewett <jimjjewett@users.sourceforge.net>,
|
|
|
|
|
Skip Montanaro <skip@pobox.com>
|
2003-06-09 00:04:58 -04:00
|
|
|
|
Status: Draft
|
|
|
|
|
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-03-23 11:41:17 -05:00
|
|
|
|
Post-History: 09-Jun-2003, 10-Jun-2003, 27-Feb-2004, 23-Mar-2004
|
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
|
|
|
|
|
|
|
|
|
The current method for declaring class and static methods 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
|
2004-03-23 11:41:17 -05:00
|
|
|
|
transformations of a 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-03-23 11:41:17 -05:00
|
|
|
|
The current method of applying a transformation to a function or
|
|
|
|
|
method places the actual translation after the function body. For
|
|
|
|
|
large 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
|
|
|
|
|
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. While the new syntax is not yet final, the intent 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-03-25 16:45:58 -05: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
|
2004-08-05 23:36:09 -04:00
|
|
|
|
modifications to classes. For Python 2.4, only function decorators
|
|
|
|
|
are being added.
|
2004-03-25 16:45:58 -05:00
|
|
|
|
|
2004-03-30 08:39:21 -05:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
Background
|
|
|
|
|
==========
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-03-23 11:41:17 -05: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,
|
|
|
|
|
attributing the 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:
|
|
|
|
|
http://mail.python.org/pipermail/python-dev/2002-February/020005.html
|
|
|
|
|
.. _he later said:
|
|
|
|
|
http://mail.python.org/pipermail/python-dev/2002-February/020017.html
|
|
|
|
|
.. _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
|
|
|
|
|
definition and function definition are syntactically similar.
|
|
|
|
|
|
2004-08-05 23:36:09 -04:00
|
|
|
|
The discussion continued on and off on python-dev from February 2002
|
|
|
|
|
through July 2004. Many 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 place.
|
|
|
|
|
Subsequent to this, he decided that for 2.4a2 we'd have the Java-style
|
|
|
|
|
@decorator syntax. Barry Warsaw named this the 'pie-decorator'
|
|
|
|
|
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
|
|
|
|
|
little like a pie. Guido `outlined his case`_ on Python-dev,
|
|
|
|
|
including `this piece`_ on the various rejected forms.
|
|
|
|
|
|
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:
|
2004-08-09 21:51:30 -04:00
|
|
|
|
http://mail.python.org/pipermail/python-dev/2004-August/author.html
|
2004-08-05 23:36:09 -04:00
|
|
|
|
|
2004-08-06 10:27:38 -04:00
|
|
|
|
.. _this piece:
|
2004-08-05 23:36:09 -04:00
|
|
|
|
http://mail.python.org/pipermail/python-dev/2004-August/046672.html
|
|
|
|
|
|
2004-03-30 08:39:21 -05: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-03-23 11:41:17 -05:00
|
|
|
|
* work for arbitrary wrappers, including user-defined callables and
|
2004-08-05 23:36:09 -04:00
|
|
|
|
the existing builtins ``classmethod()`` and ``staticmethod()``
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
* work with multiple wrappers per definition
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-03-25 16:45:58 -05: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
|
2004-03-23 11:41:17 -05:00
|
|
|
|
code
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
* not make future extensions more difficult
|
2003-06-10 00:29:48 -04:00
|
|
|
|
|
2004-03-25 16:45:58 -05:00
|
|
|
|
* be easy to type; programs that use it are expected to use it very
|
2004-03-23 11:41:17 -05:00
|
|
|
|
frequently
|
2003-06-10 00:29:48 -04:00
|
|
|
|
|
2004-03-25 16:45:58 -05:00
|
|
|
|
* not make it more difficult to scan through code quickly. It should
|
|
|
|
|
still be easy to search for all definitions, a particular
|
2004-03-23 11:41:17 -05:00
|
|
|
|
definition, or the arguments that a function accepts
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
* not needlessly complicate secondary support tools such as
|
|
|
|
|
language-sensitive editors and other "`toy parser tools out
|
|
|
|
|
there`_"
|
2003-06-10 00:29:48 -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-05 23:36:09 -04:00
|
|
|
|
Andrew Kuchling has links to a bunch of the discussions about motivations
|
|
|
|
|
`in his blog`_.
|
|
|
|
|
|
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
|
2003-06-10 00:29:48 -04:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
Proposed 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
|
|
|
|
|
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-08-05 23:36:09 -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:
|
2004-08-05 23:36:09 -04:00
|
|
|
|
http://mail.python.org/pipermail/python-dev/2004-August/046711.html
|
2004-03-25 16:45:58 -05:00
|
|
|
|
|
2004-03-30 08:39:21 -05:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
Alternate Proposals
|
|
|
|
|
===================
|
2004-02-28 14:09:44 -05:00
|
|
|
|
|
2004-04-01 08:44:35 -05:00
|
|
|
|
Several other syntaxes have been proposed::
|
2004-02-28 14:09:44 -05:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
def func(arg1, arg2, ...) as dec1, dec2, ...:
|
|
|
|
|
pass
|
2004-02-28 14:09:44 -05:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
The absence of brackets makes it cumbersome to break long lists of
|
2004-03-25 16:45:58 -05:00
|
|
|
|
decorators across multiple lines, and the keyword "as" doesn't have
|
|
|
|
|
the same meaning as its use in the ``import`` statement. Plenty of
|
|
|
|
|
`alternatives to "as"`_ have been proposed. :-)
|
|
|
|
|
|
2004-03-30 08:39:21 -05:00
|
|
|
|
.. _alternatives to "as":
|
|
|
|
|
http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&threadm=mailman.236.1079968472.742.python-list%40python.org&rnum=2&prev=/groups%3Fq%3Dpython%2Bpep%2B318%26hl%3Den%26lr%3D%26ie%3DUTF-8%26oe%3DUTF-8%26selm%3Dmailman.236.1079968472.742.python-list%2540python.org%26rnum%3D2
|
2004-02-28 14:09:44 -05:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
::
|
2004-02-28 14:09:44 -05:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
def [dec1, dec2, ...] func(arg1, arg2, ...):
|
|
|
|
|
pass
|
2004-02-28 14:09:44 -05:00
|
|
|
|
|
2004-03-25 16:45:58 -05:00
|
|
|
|
This form has the disadvantage that the decorators visually assume
|
2004-03-23 11:41:17 -05:00
|
|
|
|
higher priority than the function name and argument list.
|
2004-02-28 14:09:44 -05:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
::
|
2004-02-28 14:09:44 -05:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
def func [dec1, dec2, ...] (arg1, arg2, ...):
|
|
|
|
|
pass
|
2004-02-28 14:09:44 -05:00
|
|
|
|
|
2004-03-25 16:45:58 -05:00
|
|
|
|
Quixote's `Python Template Language`_ uses this form, but only supports a
|
2004-03-23 11:41:17 -05:00
|
|
|
|
single decorator chosen from a restricted set. For short lists it
|
|
|
|
|
works okay, but for long list it separates the argument list from the
|
|
|
|
|
function name.
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-03-30 08:39:21 -05:00
|
|
|
|
.. _Python Template Language:
|
|
|
|
|
http://www.mems-exchange.org/software/quixote/doc/PTL.html
|
2004-03-25 16:45:58 -05:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
::
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
using:
|
|
|
|
|
dec1
|
|
|
|
|
dec2
|
|
|
|
|
...
|
|
|
|
|
def foo(arg1, arg2, ...):
|
|
|
|
|
pass
|
2003-06-10 00:29:48 -04:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
The function definition is not nested within the using: block making
|
|
|
|
|
it impossible to tell which objects following the block will be
|
|
|
|
|
decorated. Nesting the function definition within the using: block
|
2004-03-25 16:45:58 -05:00
|
|
|
|
suggests nesting of namespaces that doesn't exist. The name ``foo``
|
|
|
|
|
would actually exist at the same scope as the using: block. Finally,
|
|
|
|
|
it would require the introduction of a new keyword.
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-08-06 14:34:15 -04:00
|
|
|
|
The obvious alternative that nests the function within the block
|
|
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
|
|
using:
|
|
|
|
|
dec1
|
|
|
|
|
dec2
|
|
|
|
|
...
|
|
|
|
|
def foo(arg1, arg2, ...):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
has its own set of drawbacks. Having the minimal indent level be
|
|
|
|
|
three deep for methods is painful for those using limited-width
|
|
|
|
|
windows. The inconsistent indentation between methods of the same
|
|
|
|
|
class with and without decorators would be a readability problem.
|
|
|
|
|
Finally, adding or removing decorators would require reindenting the
|
|
|
|
|
entire function/method body.
|
|
|
|
|
|
2004-08-09 21:51:30 -04:00
|
|
|
|
Guido proposed and implemented a patch to support interpretation of
|
2004-04-01 08:44:35 -05:00
|
|
|
|
a `list of decorators`_ as a prefix to function definitions ::
|
|
|
|
|
|
|
|
|
|
[dec1, dec2, ...]
|
|
|
|
|
def foo(arg1, arg2, ...):
|
|
|
|
|
pass
|
|
|
|
|
|
2004-08-05 23:36:09 -04:00
|
|
|
|
For a while this was Guido's preferred solution, but negative sentiment ran
|
2004-04-01 08:44:35 -05:00
|
|
|
|
high, mostly because that syntax, though useless except for side
|
|
|
|
|
effects of the list, is already legal and thus creates a special case.
|
|
|
|
|
|
|
|
|
|
.. _list of decorators:
|
|
|
|
|
http://python.org/sf/926860
|
|
|
|
|
|
2004-08-05 23:36:09 -04:00
|
|
|
|
Another variant on the list syntax that was initially favored was::
|
2004-03-30 08:39:21 -05:00
|
|
|
|
|
2004-08-05 23:36:09 -04:00
|
|
|
|
def func(arg1, arg2, ...) [dec1, dec2]:
|
|
|
|
|
pass
|
2004-04-04 10:12:27 -04:00
|
|
|
|
|
2004-08-05 23:36:09 -04:00
|
|
|
|
Guido decided `he preferred`_ having the decorators on the line before
|
|
|
|
|
the 'def', because it was felt that a long argument list would mean
|
|
|
|
|
that the decorators would be 'hidden'
|
|
|
|
|
|
2004-08-06 10:27:38 -04:00
|
|
|
|
.. _he preferred:
|
2004-08-05 23:36:09 -04:00
|
|
|
|
http://mail.python.org/pipermail/python-dev/2004-March/043756.html
|
|
|
|
|
|
|
|
|
|
Phillip Eby and Jp Calderone both proposed variants that required
|
|
|
|
|
no new syntax, but instead used some fairly advanced introspection
|
|
|
|
|
to provide decorator-like behavoiur, but Guido was unimpressed by
|
|
|
|
|
these, stating::
|
|
|
|
|
|
|
|
|
|
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:53:20 -04:00
|
|
|
|
A `page on the Python Wiki`_ was created to summarize a number of the
|
|
|
|
|
proposals. Once it stabilizes perhaps someone would care to
|
|
|
|
|
incorporate its content into this PEP (hint, hint).
|
|
|
|
|
|
2004-08-06 10:27:38 -04:00
|
|
|
|
.. _page on the Python Wiki:
|
2004-08-05 23:53:20 -04:00
|
|
|
|
http://www.python.org/moin/PythonDecorators
|
|
|
|
|
|
|
|
|
|
|
2004-08-05 23:36:09 -04:00
|
|
|
|
Why @?
|
|
|
|
|
------
|
|
|
|
|
|
|
|
|
|
There is some history in Java using @ initially as a marker in
|
|
|
|
|
`Javadoc comments`_ and later in ... mumble mumble ... 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
|
2004-08-06 14:34:15 -04:00
|
|
|
|
version of Python, leading to possibly subtle semantic bugs. That
|
|
|
|
|
said, @ is still a fairly arbitrary 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:
|
|
|
|
|
``[|...|]``, ``*[...]*``, and ``<...>``. None gained much traction.
|
|
|
|
|
The alternatives which involve square brackets only serve to make it
|
2004-04-04 12:19:26 -04:00
|
|
|
|
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-04-04 10:12:27 -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-04-04 10:12:27 -04:00
|
|
|
|
|
2004-03-23 11:41:17 -05:00
|
|
|
|
Current Implementation
|
|
|
|
|
======================
|
2003-06-10 00:29:48 -04:00
|
|
|
|
|
2004-08-05 23:36:09 -04:00
|
|
|
|
Guido asked for a voluteer to implement his preferred syntax, and Mark
|
|
|
|
|
Russell stepped up and posted a `patch`_ to SF. The syntax accepted
|
|
|
|
|
for 2.4a2 is::
|
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-03-23 11:41:17 -05:00
|
|
|
|
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-08-05 23:36:09 -04:00
|
|
|
|
.. _patch: http://www.python.org/sf/979728
|
|
|
|
|
|
|
|
|
|
A `previous patch`_ from Michael Hudson which implements the
|
|
|
|
|
list-after-def syntax is also still kicking around.
|
|
|
|
|
|
|
|
|
|
.. _previous patch: http://starship.python.net/crew/mwh/hacks/meth-syntax-sugar-3.diff
|
2003-07-29 11:31:13 -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
|
|
|
|
|
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
|
|
|
|
|
isn't actually "wrapped" in the usual sense.
|
|
|
|
|
|
2004-03-30 08:39:21 -05:00
|
|
|
|
::
|
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
|
|
|
|
|
|
|
|
|
2. Define a class with a singleton instance. Note that once the class
|
|
|
|
|
disappears enterprising programmers would have to be more creative
|
|
|
|
|
to create more instances. (From Shane Hathaway on ``python-dev``.)
|
|
|
|
|
|
2004-03-30 08:39:21 -05:00
|
|
|
|
::
|
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
|
|
|
|
|
Anders Munch on ``python-dev``.)
|
2003-06-10 00:29:48 -04:00
|
|
|
|
|
2004-03-30 08:39:21 -05:00
|
|
|
|
::
|
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-03-31 13:19:22 -05:00
|
|
|
|
4. Enforce function argument and return types. (Note that this is not
|
|
|
|
|
exactly correct, as the returned new_f doesn't have "func" as its
|
|
|
|
|
func_name attribute.)
|
2004-03-23 11:41:17 -05:00
|
|
|
|
|
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)
|
|
|
|
|
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
|
|
|
|
|
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
|
|
|
|
|
experience with `PyProtocols`_.
|
|
|
|
|
|
2004-03-30 08:39:21 -05:00
|
|
|
|
.. _PyProtocols: http://peak.telecommunity.com/PyProtocols.html
|
2004-03-29 22:48:59 -05:00
|
|
|
|
|
2004-03-30 08:39:21 -05:00
|
|
|
|
::
|
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-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
|
|
|
|
|
2004-03-25 16:45:58 -05:00
|
|
|
|
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
|
|
|
|
|
into the language at this point. Guido expressed skepticism about
|
|
|
|
|
the concept, but various people have made some `strong arguments`_
|
|
|
|
|
(search for ``PEP 318 - posting draft``) on their behalf in
|
|
|
|
|
``python-dev``.
|
2003-06-09 00:04:58 -04:00
|
|
|
|
|
2004-03-30 08:39:21 -05:00
|
|
|
|
.. _strong arguments:
|
|
|
|
|
http://mail.python.org/pipermail/python-dev/2004-March/thread.html
|
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:
|