[Python-checkins] peps: PEP 422: Rename init_class as autodecorate
nick.coghlan
python-checkins at python.org
Sun Feb 22 15:47:20 CET 2015
https://hg.python.org/peps/rev/0ca7ce244d19
changeset: 5701:0ca7ce244d19
user: Nick Coghlan <ncoghlan at gmail.com>
date: Mon Feb 23 00:47:12 2015 +1000
summary:
PEP 422: Rename init_class as autodecorate
files:
pep-0422.txt | 88 +++++++++++++++++++++++++++++----------
1 files changed, 64 insertions(+), 24 deletions(-)
diff --git a/pep-0422.txt b/pep-0422.txt
--- a/pep-0422.txt
+++ b/pep-0422.txt
@@ -21,9 +21,9 @@
This PEP proposes to instead support a wide range of customisation
scenarios through a new ``namespace`` parameter in the class header, and
-a new ``__init_class__`` hook in the class body.
+a new ``__autodecorate__`` hook in the class body.
-The new mechanism is also much easier to understand and use than
+The new mechanism should be easier to understand and use than
implementing a custom metaclass, and thus should provide a gentler
introduction to the full power Python's metaclass machinery.
@@ -109,16 +109,16 @@
but potentially without the full flexibility of the Python 2 style
``__metaclass__`` hook
-One mechanism that can achieve this goal is to add a new class
-initialisation hook, modelled directly on the existing instance
-initialisation hook, but with the signature constrained to match that
-of an ordinary class decorator.
+One mechanism that can achieve this goal is to add a new implicit class
+decoration hook, modelled directly on the existing explicit class
+decorators, but defined in the class body or in a parent class, rather than
+being part of the class definition header.
Specifically, it is proposed that class definitions be able to provide a
class initialisation hook as follows::
class Example:
- def __init_class__(cls):
+ def __autodecorate__(cls):
# This is invoked after the class is created, but before any
# explicit decorators are called
# The usual super() mechanisms are used to correctly support
@@ -128,14 +128,14 @@
If present on the created object, this new hook will be called by the class
creation machinery *after* the ``__class__`` reference has been initialised.
For ``types.new_class()``, it will be called as the last step before
-returning the created class object. ``__init_class__`` is implicitly
+returning the created class object. ``__autodecorate__`` is implicitly
converted to a class method when the class is created (prior to the hook
being invoked).
-If a metaclass wishes to block class initialisation for some reason, it
-must arrange for ``cls.__init_class__`` to trigger ``AttributeError``.
+If a metaclass wishes to block implicit class decoration for some reason, it
+must arrange for ``cls.__autodecorate__`` to trigger ``AttributeError``.
-Note, that when ``__init_class__`` is called, the name of the class is not
+Note, that when ``__autodecorate__`` is called, the name of the class is not
yet bound to the new class object. As a consequence, the two argument form
of ``super()`` cannot be used to call methods (e.g., ``super(Example, cls)``
wouldn't work in the example above). However, the zero argument form of
@@ -158,7 +158,7 @@
an ordered dictionary as the class namespace::
class OrderedExample(namespace=collections.OrderedDict):
- def __init_class__(cls):
+ def __autodecorate__(cls):
# cls.__dict__ is still a read-only proxy to the class namespace,
# but the underlying storage is an OrderedDict instance
@@ -220,12 +220,12 @@
parents of a class definition. This risk also makes it very difficult to
*add* a metaclass to a class that has previously been published without one.
-By contrast, adding an ``__init_class__`` method to an existing type poses
+By contrast, adding an ``__autodecorate__`` method to an existing type poses
a similar level of risk to adding an ``__init__`` method: technically, there
is a risk of breaking poorly implemented subclasses, but when that occurs,
it is recognised as a bug in the subclass rather than the library author
breaching backwards compatibility guarantees. In fact, due to the constrained
-signature of ``__init_class__``, the risk in this case is actually even
+signature of ``__autodecorate__``, the risk in this case is actually even
lower than in the case of ``__init__``.
@@ -243,11 +243,33 @@
For use cases that don't involve completely replacing the defined class,
Python 2 code that dynamically set ``__metaclass__`` can now dynamically
-set ``__init_class__`` instead. For more advanced use cases, introduction of
+set ``__autodecorate__`` instead. For more advanced use cases, introduction of
an explicit metaclass (possibly made available as a required base class) will
still be necessary in order to support Python 3.
+Design Notes
+============
+
+
+Determining if the class being decorated is the base class
+----------------------------------------------------------
+
+In the body of an ``__autodecorate__`` method, as in any other class method,
+``__class__`` will be bound to the class declaring the method, while the
+value passed in may be a subclass.
+
+This makes it relatively straightforward to skip processing the base class
+if necessary::
+
+ class Example:
+ def __autodecorate__(cls):
+ # Don't process the base class
+ if cls is __class__:
+ return
+ # Process subclasses here
+
+
New Ways of Using Classes
=========================
@@ -354,21 +376,39 @@
=======================
-Calling ``__init_class__`` from ``type.__init__``
--------------------------------------------------
+Calling ``__autodecorate__`` from ``type.__init__``
+---------------------------------------------------
Calling the new hook automatically from ``type.__init__``, would achieve most
of the goals of this PEP. However, using that approach would mean that
-``__init_class__`` implementations would be unable to call any methods that
+``__autodecorate__`` implementations would be unable to call any methods that
relied on the ``__class__`` reference (or used the zero-argument form of
``super()``), and could not make use of those features themselves.
-Requiring an explict decorator on ``__init_class__``
-----------------------------------------------------
+Calling the automatic decoration hook ``__init_class__``
+--------------------------------------------------------
+
+Earlier versions of the PEP used the name ``__init_class__`` for the name
+of the new hook. There were three significant problems with this name:
+
+* it was hard to remember if the correct spelling was ``__init_class__`` or
+ ``__class_init__``
+* the use of "init" in the name suggested the signature should match that
+ of ``type.__init__``, which is not the case
+* the use of "init" in the name suggested the method would be run as part
+ of class construction, which is not the case
+
+The new name ``__autodecorate__`` was chosen to make it clear that the new
+initialisation hook is most usefully thought of as an implicitly invoked
+class decorator, rather than as being like an ``__init__`` method.
+
+
+Requiring an explicit decorator on ``__autodecorate__``
+-------------------------------------------------------
Originally, this PEP required the explicit use of ``@classmethod`` on the
-``__init_class__`` decorator. It was made implicit since there's no
+``__autodecorate__`` decorator. It was made implicit since there's no
sensible interpretation for leaving it out, and that case would need to be
detected anyway in order to give a useful error message.
@@ -393,9 +433,9 @@
Reference Implementation
========================
-A reference implementation for __init_class__ has been posted to the
-`issue tracker`_. It does not yet include the new ``namespace`` parameter
-for ``type.__prepare__``.
+A reference implementation for ``__autodecorate__`` has been posted to the
+`issue tracker`_. It uses the original ``__init_class__`` naming and does
+not yet include the new ``namespace`` parameter for ``type.__prepare__``.
TODO
====
--
Repository URL: https://hg.python.org/peps
More information about the Python-checkins
mailing list