[Python-3000] Adding class decorators to PEP 318
Guido van Rossum
guido at python.org
Tue May 1 19:19:21 CEST 2007
I don't like this -- it seems like rewriting history to me. I'd rather
leave PEP 318 alone and create a new PEP. Of course the new PEP can be
short because it can refer to PEP 318.
--Guido
On 5/1/07, Collin Winter <collinw at gmail.com> wrote:
> In talking to Neal Norwitz about this, I don't see a need for a
> separate PEP for class decorators; we already have a decorators PEP,
> #318. The following is a proposed patch to PEP 318 that adds in class
> decorators.
>
> Collin Winter
>
>
> Index: pep-0318.txt
> ===================================================================
> --- pep-0318.txt (revision 55034)
> +++ pep-0318.txt (working copy)
> @@ -1,5 +1,5 @@
> PEP: 318
> -Title: Decorators for Functions and Methods
> +Title: Decorators for Functions, Methods and Classes
> Version: $Revision$
> Last-Modified: $Date$
> Author: Kevin D. Smith, Jim Jewett, Skip Montanaro, Anthony Baxter
> @@ -9,7 +9,7 @@
> 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,
> - 2-Sep-2004
> + 2-Sep-2004, 30-Apr-2007
>
>
> WarningWarningWarning
> @@ -22,24 +22,40 @@
> negatives of each form.
>
>
> +UpdateUpdateUpdate
> +==================
> +
> +In April 2007, this PEP was updated to reflect the evolution of the Python
> +community's attitude toward class decorators. Though they had previously
> +been rejected as too obscure and with limited use-cases, by mid-2006,
> +class decorators had come to be seen as the logical next step, with some
> +wondering why they hadn't been included originally. As a result, class
> +decorators will ship in Python 2.6.
> +
> +This PEP has been modified accordingly, with references to class decorators
> +injected into the narrative. While some references to the lack of class
> +decorators have been left in place to preserve the historical record, others
> +have been removed for the sake of coherence.
> +
> +
> 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, methods and classes (for
> +instance, declaring a method 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, method or class declaration.
>
>
> Motivation
> ==========
>
> -The current method of applying a transformation to a function or method
> -places the actual transformation 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
> +The current method of applying a transformation to a function, method or class
> +places the actual transformation after the body. For large
> +code blocks this separates a key component of the object's behavior from
> +the definition of the rest of the object's external interface. For
> example::
>
> def foo(self):
> @@ -69,14 +85,22 @@
> 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.
> +to having an easier way to make simple modifications to classes. The
> +following is much clearer than the metaclass-based alternative::
>
> + @singleton
> + class Foo(object):
> + pass
>
> +Because of the greater ease-of-use of class decorators and the symmetry
> +with function and method decorators, class decorators will be included in
> +Python 2.6.
> +
> +
> Why Is This So Hard?
> --------------------
>
> -Two decorators (``classmethod()`` and ``staticmethod()``) have been
> +Two method 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
> @@ -135,11 +159,16 @@
> .. _gareth mccaughan:
> 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
> +Class decorations seemed like an obvious next step because class
> definition and function definition are syntactically similar,
> -however Guido remains unconvinced, and class decorators will almost
> -certainly not be in Python 2.4.
> +however Guido was not convinced of their usefulness, and class
> +decorators were not in Python 2.4. `The issue was revisited`_ in March 2006
> +and sufficient use-cases were found to justify the inclusion of class
> +decorators in Python 2.6.
>
> +.. _The issue was revisited:
> + http://mail.python.org/pipermail/python-dev/2006-March/062942.html
> +
> 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
> @@ -147,8 +176,8 @@
> 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.
> +Pie-thon Parrot shootout which was occuring around the same time as
> +the decorator syntax debate, 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.
>
> @@ -250,6 +279,19 @@
> decorators are near the function declaration. The @ sign makes it clear
> that something new is going on here.
>
> +Python 2.6's class decorators work similarly::
> +
> + @dec2
> + @dec1
> + class Foo:
> + pass
> +
> +This is equivalent to::
> +
> + class Foo:
> + pass
> + Foo = dec2(dec1(Foo))
> +
> 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,
> @@ -321,7 +363,7 @@
> 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 an effect on a following line. The syntax available in 2.4a3
> -requires one decorator per line (in a2, multiple decorators could be
> +requires one decorator per line (in 2.4a2, multiple decorators could be
> specified on the same line).
>
> People also complained that the syntax quickly got unwieldy when
> @@ -330,52 +372,61 @@
> 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
> +the function/class body -- they are obviously executed at the time the object
> is defined.
>
> -Another advantage is that a prefix to the function definition fits
> +Another advantage is that a prefix to the definition fits
> the idea of knowing about a change to the semantics of the code before
> -the code itself, thus you know how to interpret the code's semantics
> +the code itself. This way, you know 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' or 'class', 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' or 'class' and the object's
> +name, or between the name and the argument list::
>
> def @classmethod foo(arg1,arg2):
> pass
> +
> + class @singleton Foo(arg1, arg2):
> + pass
>
> def @accepts(int,int), at returns(float) bar(low,high):
> pass
>
> def foo @classmethod (arg1,arg2):
> pass
> +
> + class Foo @singleton (arg1, arg2):
> + pass
>
> def bar @accepts(int,int), at returns(float) (low,high):
> pass
>
> There are a couple of objections to this form. The first is that it
> -breaks easily 'greppability' of the source -- you can no longer search
> +breaks easy 'greppability' of the source -- you can no longer search
> for 'def foo(' and find the definition of the function. The second,
> more serious, objection is that in the case of multiple decorators, the
> syntax would be extremely unwieldy.
>
> The next form, which has had a number of strong proponents, is to have
> the decorators between the argument list and the trailing ``:`` in the
> -'def' line::
> +'def' or 'class' line::
>
> def foo(arg1,arg2) @classmethod:
> pass
>
> def bar(low,high) @accepts(int,int), at returns(float):
> pass
> +
> + class Foo(object) @singleton:
> + pass
>
> Guido `summarized the arguments`_ against this form (many of which also
> apply to the previous form) as:
> @@ -403,15 +454,19 @@
> @accepts(int,int)
> @returns(float)
> pass
> +
> + class Foo(object):
> + @singleton
> + 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
> +the suite body to determine the decorators. In addition, even though
> +the code is inside the suite body, it is not executed when the code
> 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
> +The final form is a new block that encloses the function or clas. For this
> example, we'll use a 'decorate' keyword, as it makes no sense with the
> @syntax. ::
>
> @@ -425,9 +480,14 @@
> returns(float)
> def bar(low,high):
> pass
> +
> + decorate:
> + singleton
> + class Foo(object):
> + pass
>
> This form would result in inconsistent indentation for decorated and
> -undecorated methods. In addition, a decorated method's body would start
> +undecorated code. In addition, a decorated object's body would start
> three indent levels in.
>
>
> @@ -444,6 +504,10 @@
> @returns(float)
> def bar(low,high):
> pass
> +
> + @singleton
> + class Foo(object):
> + pass
>
> The major objections against this syntax are that the @ symbol is
> not currently used in Python (and is used in both IPython and Leo),
> @@ -461,6 +525,10 @@
> |returns(float)
> def bar(low,high):
> pass
> +
> + |singleton
> + class Foo(object):
> + pass
>
> This is a variant on the @decorator syntax -- it has the advantage
> that it does not break IPython and Leo. Its major disadvantage
> @@ -476,6 +544,10 @@
> [accepts(int,int), returns(float)]
> def bar(low,high):
> pass
> +
> + [singleton]
> + class Foo(object):
> + pass
>
> The major objection to the list syntax is that it's currently
> meaningful (when used in the form before the method). It's also
> @@ -490,6 +562,10 @@
> <accepts(int,int), returns(float)>
> def bar(low,high):
> pass
> +
> + <singleton>
> + class Foo(object):
> + pass
>
> None of these alternatives gained much traction. The alternatives
> which involve square brackets only serve to make it obvious that the
> @@ -659,7 +735,10 @@
> .. _subsequently rejected:
> http://mail.python.org/pipermail/python-dev/2004-September/048518.html
>
> +For Python 2.6, the Python grammar and compiler were modified to allow
> +class decorators in addition to function and method decorators.
>
> +
> Community Consensus
> -------------------
> _______________________________________________
> Python-3000 mailing list
> Python-3000 at python.org
> http://mail.python.org/mailman/listinfo/python-3000
> Unsubscribe: http://mail.python.org/mailman/options/python-3000/guido%40python.org
>
--
--Guido van Rossum (home page: http://www.python.org/~guido/)
More information about the Python-3000
mailing list