[Python-checkins] peps: PEP 422: Make __autodecorate__ a true decorator
nick.coghlan
python-checkins at python.org
Mon Feb 23 12:34:46 CET 2015
https://hg.python.org/peps/rev/922b91d5b23d
changeset: 5704:922b91d5b23d
user: Nick Coghlan <ncoghlan at gmail.com>
date: Mon Feb 23 21:34:36 2015 +1000
summary:
PEP 422: Make __autodecorate__ a true decorator
* __autodecorate__ is now defined as a true decorator that can
replace the class object entirely
* question whether the namespace parameter is sufficiently
valuable to be worth the extra complexity, or if Eric Snow's
idea of using an ordered dict by default would suffice
files:
pep-0422.txt | 96 +++++++++++++++++++++++++++++++++++++--
1 files changed, 90 insertions(+), 6 deletions(-)
diff --git a/pep-0422.txt b/pep-0422.txt
--- a/pep-0422.txt
+++ b/pep-0422.txt
@@ -129,6 +129,18 @@
# The usual super() mechanisms are used to correctly support
# multiple inheritance. The class decorator style signature helps
# ensure that invoking the parent class is as simple as possible.
+ cls = super().__autodecorate__()
+ return cls
+
+To simplify the cooperative multiple inheritance case, ``object`` will gain
+a default implementation of the hook that returns the class unmodified:
+
+ class object:
+ def __autodecorate__(cls):
+ return cls
+
+If a metaclass wishes to block implicit class decoration for some reason, it
+must arrange for ``cls.__autodecorate__`` to trigger ``AttributeError``.
If present on the created object, this new hook will be called by the class
creation machinery *after* the ``__class__`` reference has been initialised.
@@ -137,9 +149,6 @@
converted to a class method when the class is created (prior to the hook
being invoked).
-If a metaclass wishes to block implicit class decoration for some reason, it
-must arrange for ``cls.__autodecorate__`` to trigger ``AttributeError``.
-
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)``
@@ -151,7 +160,7 @@
inclusion in the language definition `more than 10 years ago`_, and a
similar mechanism has long been supported by `Zope's ExtensionClass`_),
but the situation has changed sufficiently in recent years that
-the idea is worth reconsidering.
+the idea is worth reconsidering for inclusion as a native language feature.
In addition, the introduction of the metaclass ``__prepare__`` method in PEP
3115 allows a further enhancement that was not possible in Python 2: this
@@ -269,6 +278,7 @@
class Example:
def __autodecorate__(cls):
+ cls = super().__autodecorate__()
# Don't process the base class
if cls is __class__:
return
@@ -276,6 +286,58 @@
...
+Replacing a class with a different kind of object
+-------------------------------------------------
+
+As an implicit decorator, ``__autodecorate__`` is able to relatively easily
+replace the defined class with a different kind of object. Technically
+custom metaclasses and even ``__new__`` methods can already do this
+implicitly, but the decorator model makes such code much easier to understand
+and implement.
+
+ class BuildDict:
+ def __autodecorate__(cls):
+ cls = super().__autodecorate__()
+ # Don't process the base class
+ if cls is __class__:
+ return
+ # Convert subclasses to ordinary dictionaries
+ return cls.__dict__.copy()
+
+It's not clear why anyone would ever do this implicitly based on inheritance
+rather than just using an explicit decorator, but the possibility seems worth
+noting.
+
+
+Open Questions
+==============
+
+Is the ``namespace`` concept worth the extra complexity?
+--------------------------------------------------------
+
+Unlike the new ``__autodecorate__`` hook the proposed ``namespace`` keyword
+argument is not automatically inherited by subclasses. Given the way this
+proposal is currently written , the only way to get a special namespace used
+consistently in subclasses is still to write a custom metaclass with a
+suitable ``__prepare__`` implementation.
+
+Changing the custom namespace factory to also be inherited would
+significantly increase the complexity of this proposal, and introduce a
+number of the same potential base class conflict issues as arise with the
+use of custom metaclasses.
+
+Eric Snow has put forward a
+`separate proposal <https://mail.python.org/pipermail/python-dev/2013-June/127103.html>`__
+to instead make the execution namespace for class bodies an ordered dictionary
+by default, and capture the class attribute definition order for future
+reference as an attribute (e.g. ``__definition_order__``) on the class object.
+
+Eric's suggested approach may be a better choice for a new default behaviour
+for type that combines well with the proposed ``__autodecorate__`` hook,
+leaving the more complex configurable namespace factory idea to a custom
+metaclass like the one shown below.
+
+
New Ways of Using Classes
=========================
@@ -428,6 +490,26 @@
explicitly say anything one way or the other).
+Making ``__autodecorate__`` implicitly static, like ``__new__``
+---------------------------------------------------------------
+
+While it accepts the class to be instantiated as the first argument,
+``__new__`` is actually implicitly treated as a static method rather than
+as a class method. This allows it to be readily extracted from its
+defining class and called directly on a subclass, rather than being
+coupled to the class object it is retrieved from.
+
+Such behaviour initially appears to be potentially useful for the
+new ``__autodecorate__`` hook, as it would allow ``__autodecorate__``
+methods to readily be used as explicit decorators on other classes.
+
+However, that apparent support would be an illusion as it would only work
+correctly if invoked on a subclass, in which case the method can just as
+readily be retrieved from the subclass and called that way. Unlike
+``__new__``, there's no issue with potentially changing method signatures at
+different points in the inheritance chain.
+
+
Passing in the namespace directly rather than a factory function
----------------------------------------------------------------
@@ -443,8 +525,10 @@
========================
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__``.
+`issue tracker`_. It uses the original ``__init_class__`` naming. does not yet
+allow the implicit decorator to replace the class with a different object and
+does not implement the suggested ``namespace`` parameter for
+``type.__prepare__``.
TODO
====
--
Repository URL: https://hg.python.org/peps
More information about the Python-checkins
mailing list