PEP: 3129 Title: Class Decorators Version: $Revision$ Last-Modified:
$Date$ Author: Collin Winter <collinwinter@google.com> Status: Final
Type: Standards Track Content-Type: text/x-rst Created: 01-May-2007
Python-Version: 3.0 Post-History: 07-May-2007

Abstract

This PEP proposes class decorators, an extension to the function and
method decorators introduced in PEP 318.

Rationale

When function decorators were originally debated for inclusion in Python
2.4, class decorators were seen as
obscure and unnecessary <318#motivation> thanks to metaclasses. After
several years' experience with the Python 2.4.x series of releases and
an increasing familiarity with function decorators and their uses, the
BDFL and the community re-evaluated class decorators and recommended
their inclusion in Python 3.0[1].

The motivating use-case was to make certain constructs more easily
expressed and less reliant on implementation details of the CPython
interpreter. While it is possible to express class decorator-like
functionality using metaclasses, the results are generally unpleasant
and the implementation highly fragile[2]. In addition, metaclasses are
inherited, whereas class decorators are not, making metaclasses
unsuitable for some, single class-specific uses of class decorators. The
fact that large-scale Python projects like Zope were going through these
wild contortions to achieve something like class decorators won over the
BDFL.

Semantics

The semantics and design goals of class decorators are the same as for
function decorators (318#current-syntax, 318#design-goals); the only
difference is that you're decorating a class instead of a function. The
following two snippets are semantically identical:

    class A:
      pass
    A = foo(bar(A))


    @foo
    @bar
    class A:
      pass

For a detailed examination of decorators, please refer to PEP 318.

Implementation

Adapting Python's grammar to support class decorators requires modifying
two rules and adding a new rule:

    funcdef: [decorators] 'def' NAME parameters ['->' test] ':' suite

    compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt |
                   with_stmt | funcdef | classdef

need to be changed to :

    decorated: decorators (classdef | funcdef)

    funcdef: 'def' NAME parameters ['->' test] ':' suite

    compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt |
                   with_stmt | funcdef | classdef | decorated

Adding decorated is necessary to avoid an ambiguity in the grammar.

The Python AST and bytecode must be modified accordingly.

A reference implementation[3] has been provided by Jack Diederich.

Acceptance

There was virtually no discussion following the posting of this PEP,
meaning that everyone agreed it should be accepted.

The patch was committed to Subversion as revision 55430.

References

Copyright

This document has been placed in the public domain.



  Local Variables: mode: indented-text indent-tabs-mode: nil
  sentence-end-double-space: t fill-column: 70 coding: utf-8 End:

[1] https://mail.python.org/pipermail/python-dev/2006-March/062942.html

[2] https://mail.python.org/pipermail/python-dev/2006-March/062888.html

[3] https://bugs.python.org/issue1671208