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: 1-May-2007
Python-Version: 3.0 Post-History: 7-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
\[\#obscure\]\_ 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 \[\#approval\]\_.

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 \[\#motivation\]\_. 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 (\[\#semantics\]*, \[\#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 \[\#implementation\]\_ 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
==========

.. \[\#obscure\] http://www.python.org/dev/peps/pep-0318/\#motivation

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

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

.. \[\#semantics\]
http://www.python.org/dev/peps/pep-0318/\#current-syntax

.. \[\#goals\] http://www.python.org/dev/peps/pep-0318/\#design-goals

.. \[\#implementation\] https://bugs.python.org/issue1671208

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:
