[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