2016-06-07 20:44:13 -04:00
|
|
|
|
PEP: 520
|
|
|
|
|
Title: Ordered Class Definition Namespace
|
|
|
|
|
Version: $Revision$
|
|
|
|
|
Last-Modified: $Date$
|
|
|
|
|
Author: Eric Snow <ericsnowcurrently@gmail.com>
|
|
|
|
|
Status: Draft
|
|
|
|
|
Type: Standards Track
|
|
|
|
|
Content-Type: text/x-rst
|
|
|
|
|
Created: 7-Jun-2016
|
|
|
|
|
Python-Version: 3.6
|
|
|
|
|
Post-History: 7-Jun-2016
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Abstract
|
|
|
|
|
========
|
|
|
|
|
|
2016-06-11 21:42:03 -04:00
|
|
|
|
When a class is defined using a ``class`` statement, the class body is
|
|
|
|
|
executed within a namespace. After the execution completes, that
|
|
|
|
|
namespace is copied into new ``dict`` and the original definition
|
|
|
|
|
namespace is discarded. The new copy is stored away as the class's
|
|
|
|
|
namespace and is exposed as ``__dict__`` through a read-only proxy.
|
|
|
|
|
|
2016-06-07 20:44:13 -04:00
|
|
|
|
This PEP changes the default class definition namespace to ``OrderedDict``.
|
2016-06-11 21:42:03 -04:00
|
|
|
|
The long-lived class namespace (``__dict__``) will remain a ``dict``.
|
2016-06-07 20:44:13 -04:00
|
|
|
|
Furthermore, the order in which the attributes are defined in each class
|
2016-06-07 23:09:27 -04:00
|
|
|
|
body will now be preserved in the ``__definition_order__`` attribute of
|
|
|
|
|
the class. This allows introspection of the original definition order,
|
|
|
|
|
e.g. by class decorators.
|
2016-06-07 20:44:13 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Motivation
|
|
|
|
|
==========
|
|
|
|
|
|
|
|
|
|
Currently the namespace used during execution of a class body defaults
|
|
|
|
|
to ``dict``. If the metaclass defines ``__prepare__()`` then the result
|
|
|
|
|
of calling it is used. Thus, before this PEP, if you needed your class
|
|
|
|
|
definition namespace to be ``OrderedDict`` you had to use a metaclass.
|
|
|
|
|
|
|
|
|
|
Metaclasses introduce an extra level of complexity to code and in some
|
|
|
|
|
cases (e.g. conflicts) are a problem. So reducing the need for them is
|
|
|
|
|
worth doing when the opportunity presents itself. Given that we now have
|
|
|
|
|
a C implementation of ``OrderedDict`` and that ``OrderedDict`` is the
|
|
|
|
|
common use case for ``__prepare__()``, we have such an opportunity by
|
|
|
|
|
defaulting to ``OrderedDict``.
|
|
|
|
|
|
|
|
|
|
The usefulness of ``OrderedDict``-by-default is greatly increased if the
|
|
|
|
|
definition order is directly introspectable on classes afterward,
|
|
|
|
|
particularly by code that is independent of the original class definition.
|
|
|
|
|
One of the original motivating use cases for this PEP is generic class
|
|
|
|
|
decorators that make use of the definition order.
|
|
|
|
|
|
|
|
|
|
Changing the default class definition namespace has been discussed a
|
|
|
|
|
number of times, including on the mailing lists and in PEP 422 and
|
|
|
|
|
PEP 487 (see the References section below).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Specification
|
|
|
|
|
=============
|
|
|
|
|
|
|
|
|
|
* the default class *definition* namespace is now ``OrderdDict``
|
|
|
|
|
* the order in which class attributes are defined is preserved in the
|
|
|
|
|
new ``__definition_order__`` attribute on each class
|
|
|
|
|
* "dunder" attributes (e.g. ``__init__``, ``__module__``) are ignored
|
2016-06-11 22:22:50 -04:00
|
|
|
|
* ``__definition_order__`` is a ``tuple`` (or ``None``)
|
2016-06-07 20:44:13 -04:00
|
|
|
|
* ``__definition_order__`` is a read-only attribute
|
|
|
|
|
* ``__definition_order__`` is always set:
|
|
|
|
|
|
2016-06-11 22:22:50 -04:00
|
|
|
|
1. if ``__definition_order__`` is defined in the class body then it
|
|
|
|
|
must be a ``tuple`` of identifiers or ``None``; any other value
|
|
|
|
|
will result in ``TypeError``
|
2016-06-07 23:09:27 -04:00
|
|
|
|
2. classes that do not have a class definition (e.g. builtins) have
|
2016-06-07 20:44:13 -04:00
|
|
|
|
their ``__definition_order__`` set to ``None``
|
2016-06-07 23:09:27 -04:00
|
|
|
|
3. classes for which `__prepare__()`` returned something other than
|
2016-06-07 20:44:13 -04:00
|
|
|
|
``OrderedDict`` (or a subclass) have their ``__definition_order__``
|
|
|
|
|
set to ``None`` (except where #1 applies)
|
|
|
|
|
|
2016-06-11 22:22:50 -04:00
|
|
|
|
The following code demonstrates roughly equivalent semantics for the
|
|
|
|
|
default behavior::
|
2016-06-07 20:44:13 -04:00
|
|
|
|
|
|
|
|
|
class Meta(type):
|
|
|
|
|
def __prepare__(cls, *args, **kwargs):
|
|
|
|
|
return OrderedDict()
|
|
|
|
|
|
|
|
|
|
class Spam(metaclass=Meta):
|
|
|
|
|
ham = None
|
|
|
|
|
eggs = 5
|
|
|
|
|
__definition_order__ = tuple(k for k in locals()
|
2016-06-07 23:09:27 -04:00
|
|
|
|
if (not k.startswith('__') or
|
|
|
|
|
not k.endswith('__')))
|
2016-06-07 20:44:13 -04:00
|
|
|
|
|
|
|
|
|
Note that [pep487_] proposes a similar solution, albeit as part of a
|
|
|
|
|
broader proposal.
|
|
|
|
|
|
|
|
|
|
Why a tuple?
|
|
|
|
|
------------
|
|
|
|
|
|
|
|
|
|
Use of a tuple reflects the fact that we are exposing the order in
|
|
|
|
|
which attributes on the class were *defined*. Since the definition
|
|
|
|
|
is already complete by the time ``definition_order__`` is set, the
|
|
|
|
|
content and order of the value won't be changing. Thus we use a type
|
|
|
|
|
that communicates that state of immutability.
|
|
|
|
|
|
|
|
|
|
Why a read-only attribute?
|
|
|
|
|
--------------------------
|
|
|
|
|
|
|
|
|
|
As with the use of tuple, making ``__definition_order__`` a read-only
|
|
|
|
|
attribute communicates the fact that the information it represents is
|
|
|
|
|
complete. Since it represents the state of a particular one-time event
|
|
|
|
|
(execution of the class definition body), allowing the value to be
|
|
|
|
|
replaced would reduce confidence that the attribute corresponds to the
|
|
|
|
|
original class body.
|
|
|
|
|
|
|
|
|
|
If a use case for a writable (or mutable) ``__definition_order__``
|
|
|
|
|
arises, the restriction may be loosened later. Presently this seems
|
|
|
|
|
unlikely and furthermore it is usually best to go immutable-by-default.
|
|
|
|
|
|
|
|
|
|
Note that ``__definition_order__`` is centered on the class definition
|
|
|
|
|
body. The use cases for dealing with the class namespace (``__dict__``)
|
|
|
|
|
post-definition are a separate matter. ``__definition_order__`` would
|
2016-06-11 22:22:50 -04:00
|
|
|
|
be a significantly misleading name for a feature focused on more than
|
|
|
|
|
class definition.
|
2016-06-07 20:44:13 -04:00
|
|
|
|
|
|
|
|
|
See [nick_concern_] for more discussion.
|
|
|
|
|
|
|
|
|
|
Why ignore "dunder" names?
|
|
|
|
|
--------------------------
|
|
|
|
|
|
|
|
|
|
Names starting and ending with "__" are reserved for use by the
|
|
|
|
|
interpreter. In practice they should not be relevant to the users of
|
2016-06-07 23:16:56 -04:00
|
|
|
|
``__definition_order__``. Instead, for nearly everyone they would only
|
2016-06-07 20:44:13 -04:00
|
|
|
|
be clutter, causing the same extra work for everyone.
|
|
|
|
|
|
2016-06-11 22:22:50 -04:00
|
|
|
|
Why None instead of an empty tuple?
|
|
|
|
|
-----------------------------------
|
|
|
|
|
|
|
|
|
|
A key objective of adding ``__definition_order__`` is to preserve
|
|
|
|
|
information in class definitions which was lost prior to this PEP.
|
|
|
|
|
One consequence is that ``__definition_order__`` implies an original
|
|
|
|
|
class definition. Using ``None`` allows us to clearly distinquish
|
|
|
|
|
classes that do not have a definition order. An empty tuple clearly
|
|
|
|
|
indicates a class that came from a definition statement but did not
|
|
|
|
|
define any attributes there.
|
|
|
|
|
|
|
|
|
|
Why None instead of not setting the attribute?
|
|
|
|
|
----------------------------------------------
|
|
|
|
|
|
|
|
|
|
The absence of an attribute requires more complex handling than ``None``
|
|
|
|
|
does for consumers of ``__definition_order__``.
|
|
|
|
|
|
|
|
|
|
Why constrain manually set values?
|
|
|
|
|
----------------------------------
|
|
|
|
|
|
|
|
|
|
If ``__definition_order__`` is manually set in the class body then it
|
|
|
|
|
will be used. We require it to be a tuple of identifiers (or ``None``)
|
|
|
|
|
so that consumers of ``__definition_order__`` may have a consistent
|
|
|
|
|
expectation for the value. That helps maximize the feature's
|
|
|
|
|
usefulness.
|
|
|
|
|
|
2016-06-07 20:44:13 -04:00
|
|
|
|
Why is __definition_order__ even necessary?
|
|
|
|
|
-------------------------------------------
|
|
|
|
|
|
2016-06-07 23:16:56 -04:00
|
|
|
|
Since the definition order is not preserved in ``__dict__``, it is
|
2016-06-07 20:44:13 -04:00
|
|
|
|
lost once class definition execution completes. Classes *could*
|
|
|
|
|
explicitly set the attribute as the last thing in the body. However,
|
|
|
|
|
then independent decorators could only make use of classes that had done
|
|
|
|
|
so. Instead, ``__definition_order__`` preserves this one bit of info
|
|
|
|
|
from the class body so that it is universally available.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Compatibility
|
|
|
|
|
=============
|
|
|
|
|
|
|
|
|
|
This PEP does not break backward compatibility, except in the case that
|
|
|
|
|
someone relies *strictly* on ``dict`` as the class definition namespace.
|
|
|
|
|
This shouldn't be a problem.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Changes
|
|
|
|
|
=============
|
|
|
|
|
|
|
|
|
|
In addition to the class syntax, the following expose the new behavior:
|
|
|
|
|
|
|
|
|
|
* builtins.__build_class__
|
|
|
|
|
* types.prepare_class
|
|
|
|
|
* types.new_class
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Other Python Implementations
|
|
|
|
|
============================
|
|
|
|
|
|
|
|
|
|
Pending feedback, the impact on Python implementations is expected to
|
|
|
|
|
be minimal. If a Python implementation cannot support switching to
|
|
|
|
|
`OrderedDict``-by-default then it can always set ``__definition_order__``
|
|
|
|
|
to ``None``.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Implementation
|
|
|
|
|
==============
|
|
|
|
|
|
|
|
|
|
The implementation is found in the tracker. [impl_]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Alternatives
|
|
|
|
|
============
|
|
|
|
|
|
2016-06-07 23:09:27 -04:00
|
|
|
|
<class>.__dict__ as OrderedDict
|
|
|
|
|
-------------------------------
|
2016-06-07 20:44:13 -04:00
|
|
|
|
|
|
|
|
|
Instead of storing the definition order in ``__definition_order__``,
|
|
|
|
|
the now-ordered definition namespace could be copied into a new
|
2016-06-07 23:09:27 -04:00
|
|
|
|
``OrderedDict``. This would then be used as the mapping proxied as
|
|
|
|
|
``__dict__``. Doing so would mostly provide the same semantics.
|
2016-06-07 20:44:13 -04:00
|
|
|
|
|
2016-06-07 23:09:27 -04:00
|
|
|
|
However, using ``OrderedDict`` for ``__dict__`` would obscure the
|
2016-06-07 20:44:13 -04:00
|
|
|
|
relationship with the definition namespace, making it less useful.
|
|
|
|
|
Additionally, doing this would require significant changes to the
|
|
|
|
|
semantics of the concrete ``dict`` C-API.
|
|
|
|
|
|
|
|
|
|
A "namespace" Keyword Arg for Class Definition
|
|
|
|
|
----------------------------------------------
|
|
|
|
|
|
|
|
|
|
PEP 422 introduced a new "namespace" keyword arg to class definitions
|
|
|
|
|
that effectively replaces the need to ``__prepare__()``. [pep422_]
|
|
|
|
|
However, the proposal was withdrawn in favor of the simpler PEP 487.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
References
|
|
|
|
|
==========
|
|
|
|
|
|
|
|
|
|
.. [impl] issue #24254
|
|
|
|
|
(https://bugs.python.org/issue24254)
|
|
|
|
|
|
|
|
|
|
.. [nick_concern] Nick's concerns about mutability
|
|
|
|
|
(https://mail.python.org/pipermail/python-dev/2016-June/144883.html)
|
|
|
|
|
|
|
|
|
|
.. [pep422] PEP 422
|
|
|
|
|
(https://www.python.org/dev/peps/pep-0422/#order-preserving-classes)
|
|
|
|
|
|
|
|
|
|
.. [pep487] PEP 487
|
|
|
|
|
(https://www.python.org/dev/peps/pep-0487/#defining-arbitrary-namespaces)
|
|
|
|
|
|
|
|
|
|
.. [orig] original discussion
|
|
|
|
|
(https://mail.python.org/pipermail/python-ideas/2013-February/019690.html)
|
|
|
|
|
|
|
|
|
|
.. [followup1] follow-up 1
|
|
|
|
|
(https://mail.python.org/pipermail/python-dev/2013-June/127103.html)
|
|
|
|
|
|
|
|
|
|
.. [followup2] follow-up 2
|
|
|
|
|
(https://mail.python.org/pipermail/python-dev/2015-May/140137.html)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Copyright
|
|
|
|
|
===========
|
|
|
|
|
This document has been placed in the public domain.
|
2016-06-07 20:47:24 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
..
|
|
|
|
|
Local Variables:
|
|
|
|
|
mode: indented-text
|
|
|
|
|
indent-tabs-mode: nil
|
|
|
|
|
sentence-end-double-space: t
|
|
|
|
|
fill-column: 70
|
|
|
|
|
coding: utf-8
|
|
|
|
|
End:
|