From b13a4cc3051137678ef8f0490e99742ab2c4232b Mon Sep 17 00:00:00 2001 From: Anthony Baxter Date: Wed, 1 Sep 2004 15:02:22 +0000 Subject: [PATCH] ding dong the witch is dead. or rather, the decorator discussion is. updating the pep. (I'm not sure if the "Community Concensus" section should be trimmed down radically now - it's a lot of words for a rejected form, and the case for the form is still available on the web and in the mailing list archives... opinions, anyone?) --- pep-0318.txt | 361 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 213 insertions(+), 148 deletions(-) diff --git a/pep-0318.txt b/pep-0318.txt index a43adc417..136ea16a0 100644 --- a/pep-0318.txt +++ b/pep-0318.txt @@ -8,49 +8,49 @@ Type: Standards Track Content-Type: text/x-rst Created: 05-Jun-2003 Python-Version: 2.4 -Post-History: 09-Jun-2003, 10-Jun-2003, 27-Feb-2004, 23-Mar-2004, 30-Aug-2004 +Post-History: 09-Jun-2003, 10-Jun-2003, 27-Feb-2004, 23-Mar-2004, 30-Aug-2004, +2-Sep-2004 WarningWarningWarning ===================== -The final decision on the syntax for 2.4a3 is not yet made. This will -be done before 2.4a3, and this document will be updated to match. -Note also that this document does not attempt to cover the huge number -of potential alternative syntaxes, nor is it an attempt to -exhaustively list all the positives and negatives of each form. +This document is meant to describe the decorator syntax and the +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 +negatives of each form. Abstract ======== -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. +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. Motivation ========== -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:: +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:: def foo(self): perform method operation foo = classmethod(foo) 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:: +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:: def foo(cls): pass @@ -65,41 +65,39 @@ declaration:: def foo(cls): pass -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. +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. Why Is This So Hard? -------------------- -Two decorators (``classmethod()`` and ``staticmethod()``) have -been available in Python since version 2.2. It's been assumed since +Two decorators (``classmethod()`` and ``staticmethod()``) have been +available in Python since version 2.2. It's been assumed since approximately that time that some syntactic support for them would eventually be added to the language. Given this assumption, one might -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 seem to be most problematic. +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 +seem to be most problematic. * Disagreement about where the "declaration of intent" belongs. - 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. + 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. * 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 - 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. + 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. * Overall unfamiliarity with the concept. For people who have a passing acquaintance with algebra (or even basic arithmetic) or have @@ -109,7 +107,7 @@ few problems seem to be most problematic. strong preexisting meme that captures the concept. * Syntax discussions in general appear to cause more contention than - almost anything else. Readers are pointed to the ternary operator + almost anything else. Readers are pointed to the ternary operator discussions that were associated with PEP 308 for another example of this. @@ -117,12 +115,12 @@ few problems seem to be most problematic. Background ========== -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, +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 initial bracketed syntax to an earlier proposal on ``comp.lang.python`` by `Gareth McCaughan`_. @@ -138,18 +136,21 @@ attributing the initial bracketed syntax to an earlier proposal on http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=slrna40k88.2h9o.Gareth.McCaughan%40g.local Class decorations seem like an obvious next step because class -definition and function definition are syntactically similar. +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 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. +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 +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 +Pie-thon Parrot shootout which was occured around 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 some of the (many) rejected forms. .. _EuroPython 2004: http://www.python.org/doc/essays/ppt/euro2004/euro2004.pdf @@ -199,8 +200,8 @@ The new syntax should frequently * not make it more difficult to scan through code quickly. It should - still be easy to search for all definitions, a particular - definition, or the arguments that a function accepts + still be easy to search for all definitions, a particular definition, + or the arguments that a function accepts * not needlessly complicate secondary support tools such as language-sensitive editors and other "`toy parser tools out @@ -208,8 +209,8 @@ The new syntax should * allow future compilers to optimize for decorators. With the hope of a JIT compiler for Python coming into existence at some point this - tends to require the syntax for decorators to come before the - function definition + tends to require the syntax for decorators to come before the function + definition * move from the end of the function, where it's currently hidden, to the front where it is more `in your face`_ @@ -246,8 +247,8 @@ This is equivalent to:: func = dec2(dec1(func)) 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. +decorators are near the function declaration. The @ sign makes it clear +that something new is going on here. The decorator statement is limited in what it can accept -- arbitrary expressions will not work. Guido preferred this because of a `gut @@ -278,8 +279,8 @@ 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:: +Decorators before the def statement are the first alternative, and the +syntax used in 2.4a2:: @classmethod def foo(arg1,arg2): @@ -290,36 +291,36 @@ and the syntax used in 2.4a2:: 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). +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 available for in 2.4a3 +requires one decorator per line (in a2, multiple decorators could be +specified on the same line). People also complained that the syntax got unworldly quickly when 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. -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. +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. -Another advantage is that being prefix to the function definition fit the -idea of knowing about a change to the semantics of the code before the -code itself, thus knowing how to interpret the code's semantics +Another advantage is that being prefix to the function definition fit +the idea of knowing about a change to the semantics of the code before +the code itself, thus knowing how to interpret the code's semantics properly without having to go back and change your initial perceptions if the syntax did not come before the function definition. 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' +the 'def', because it was felt that a long argument list would mean that +the decorators would be 'hidden' .. _he preferred: http://mail.python.org/pipermail/python-dev/2004-March/043756.html -The second form is the decorators between the def and the function -name, or the function name and the argument list:: +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 @@ -336,12 +337,12 @@ name, or the function name and the argument list:: 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. +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:: +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 @@ -349,8 +350,8 @@ in the 'def' line:: def bar(low,high) @accepts(int,int),@returns(float): pass -Guido `summarized the arguments`_ against this form (many of which -also apply to the previous form) as: +Guido `summarized 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 @@ -364,9 +365,8 @@ also apply to the previous form) as: .. _summarized 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: +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 @@ -377,16 +377,16 @@ live: @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 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. :: +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 @@ -400,8 +400,8 @@ with the @syntax. :: 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. +undecorated methods. In addition, a decorated method's body would start +three indent levels in. Syntax forms @@ -420,7 +420,7 @@ Syntax forms The major objections against this syntax are that the @ symbol is not currently used in Python (and is used in both IPython and Leo), - and that the @ symbol is not meaningful. Another objection is that + and that the @ symbol is not meaningful. Another objection is that this "wastes" a currently unused character (from a limited set) on something that is not perceived as a major use. @@ -437,8 +437,8 @@ Syntax forms This is a variant on the @decorator syntax -- it has the advantage that it does not break IPython and Leo. Its major disadvantage - compared to the @syntax is that the | symbol looks like both a - capital I and a lowercase l. + compared to the @syntax is that the | symbol looks like both a capital + I and a lowercase l. * list syntax:: @@ -474,28 +474,29 @@ Syntax forms * ``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 + 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: - 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. + 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. * _`new keyword (and block)` - This idea was the consensus alternate from comp.lang.python. Robert - Brewer wrote up a detailed `J2 proposal`_ document outlining the - arguments in favor of this. The issues with this form are: + 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: - It requires a new keyword, and therefore a ``from __future__ import decorators`` statement. @@ -508,12 +509,39 @@ Syntax forms code block, but isn't. Attempts to use statements in this block will cause a syntax error, which may confuse users. - See `Community Consensus`_ below. + 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`_. .. _J2 proposal: http://www.aminus.org/rbre/python/pydec.html -There are plenty of other variants and proposals on `the wiki page`_. + .. _rejected the proposal: + http://mail.python.org/pipermail/python-dev/2004-September/048518.html + + .. _the full response: + http://mail.python.org/pipermail/python-dev/2004-September/048518.html + +* Other forms + + There are plenty of other variants and proposals on `the wiki page`_. .. _the wiki page: http://www.python.org/moin/PythonDecorators @@ -522,18 +550,18 @@ There are plenty of other variants and proposals on `the wiki page`_. Why @? ------ -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 and what isn't is removed. of That said, @ is -still a fairly arbitrary choice. Some have suggested using | instead. +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 +and what isn't is removed. of That said, @ is still a fairly arbitrary +choice. Some have suggested using | instead. For syntax options which use a list-like syntax (no matter where it appears) to specify the decorators a few alternatives were proposed: -``[|...|]``, ``*[...]*``, and ``<...>``. +``[|...|]``, ``*[...]*``, and ``<...>``. .. _Javadoc comments: http://java.sun.com/j2se/javadoc/writingdoccomments/ @@ -545,8 +573,8 @@ Current Implementation, History =============================== Guido asked for a volunteer to implement his preferred syntax, and Mark -Russell stepped up and posted a `patch`_ to SF. The syntax accepted -for 2.4a2 is:: +Russell stepped up and posted a `patch`_ to SF. This new syntax was +available in 2.4a2. :: @dec2 @dec1 @@ -561,6 +589,10 @@ This is equivalent to:: though without the intermediate creation of a variable named ``func``. +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. + A `previous patch`_ from Michael Hudson which implements the list-after-def syntax is also still kicking around. @@ -572,19 +604,44 @@ stated that he'd re-examine a community proposal, if the community could come up with a community consensus, a decent proposal, and an implementation. After an amazing number of posts, collecting a vast number of alternatives in the `Python wiki`_, a community consensus -emerged (below). As at time of writing, we're waiting for Guido's -decision. +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. .. _Python wiki: http://www.python.org/moin/PythonDecorators +.. _subsequently rejected: + http://mail.python.org/pipermail/python-dev/2004-September/048518.html Community Consensus ------------------- -The consensus that emerged was for the proposed J2 syntax: the new -keyword ``using`` prefixing a block of decorators before the ``def`` -statement. For example:: +[editor's note: should this section be removed now?] + +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:: using: classmethod @@ -613,15 +670,21 @@ Sparks produced `a patch`_. .. _a patch: http://www.python.org/sf/1013835 +As noted previously, Guido rejected this form, outlining his problems +with it in `a message`_ to python-dev and comp.lang.python. + +.. _a message: + http://mail.python.org/pipermail/python-dev/2004-September/048518.html + Examples ======== Much of the discussion on ``comp.lang.python`` and the ``python-dev`` 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. +the ``staticmethod()`` and ``classmethod()`` builtins. This capability +is much more powerful than that. This section presents some examples of +use. 1. Define a function to be executed at exit. Note that the function isn't actually "wrapped" in the usual sense. :: @@ -639,9 +702,8 @@ some examples of use. is for example purposes only. 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``.) - :: + disappears enterprising programmers would have to be more creative to + create more instances. (From Shane Hathaway on ``python-dev``.) :: def singleton(cls): instances = {} @@ -734,14 +796,17 @@ Open Issues =========== 1. It's not yet certain that class decorators will be incorporated - into the language at this point. Guido expressed skepticism about + into the language at a future 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``. + ``python-dev``. It's exceedingly unlikely that class decorators + will be in Python 2.4. .. _strong arguments: http://mail.python.org/pipermail/python-dev/2004-March/thread.html +2. The choice of the ``@`` character will be re-examined before + Python 2.4b1. Copyright =========