Update PEP 520 per python-dev feedback.

This commit is contained in:
ericsnowcurrently 2016-06-28 11:03:29 -06:00 committed by GitHub
parent c7adf1141c
commit e901e81295
1 changed files with 63 additions and 21 deletions

View File

@ -31,9 +31,9 @@ preserved in the ``__definition_order__`` attribute of the class.
This allows introspection of the original definition order, e.g. by
class decorators.
Additionally, this PEP changes the default class definition namespace
to ``OrderedDict``. The long-lived class namespace (``__dict__``) will
remain a ``dict``.
Additionally, this PEP requires that the default class definition
namespace be ordered (e.g. ``OrderedDict``) by default. The long-
lived class namespace (``__dict__``) will remain a ``dict``.
Motivation
@ -76,7 +76,7 @@ access to the definition order by switching the definition namespace
to an ordered mapping, such as ``collections.OrderedDict``. This is
feasible using a metaclass and ``__prepare__``, as described above.
In fact, exactly this is by far the most common use case for using
``__prepare__`` (see PEP 487).
``__prepare__``.
At that point, the only missing thing for later access to the
definition order is storing it on the class before the definition
@ -89,9 +89,9 @@ First, it requires the use of 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. PEP 422 and PEP 487 discuss this at
length. 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``.
length. We have such an opportunity by using an ordered mapping (e.g.
``OrderedDict`` for CPython at least) for the default class definition
namespace, virtually eliminating the need for ``__prepare__()``.
Second, only classes that opt in to using the ``OrderedDict``-based
metaclass will have access to the definition order. This is problematic
@ -119,12 +119,24 @@ Part 1:
``OrderedDict`` (or a subclass) have their ``__definition_order__``
set to ``None`` (except where #2 applies)
Not changing:
* ``dir()`` will not depend on ``__definition_order__``
* descriptors and custom ``__getattribute__`` methods are unconstrained
regarding ``__definition_order__``
Part 2:
* the default class *definition* namespace is now ``OrderdDict``
* the default class *definition* namespace is now an ordered mapping
(e.g. ``OrderdDict``)
* ``cls.__dict__`` does not change, remaining a read-only proxy around
``dict``
Note that Python implementations which have an ordered ``dict`` won't
need to change anything
The following code demonstrates roughly equivalent semantics for the
default behavior::
The following code demonstrates roughly equivalent semantics for both
parts 1 and 2::
class Meta(type):
@classmethod
@ -159,9 +171,12 @@ 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 the ability to set ``__definition_order__`` manually allows
a dynamically created class (e.g. Cython, ``type()``) to still have
``__definition_order__`` properly set.
Note that if ``__definition_order__`` were not read-only then it would
allow dynamically created classes (e.g. by Cython) to still have
``__definition_order__`` properly set. However, if this is important
then it could be handled through specific class-creation tools, such as
``type()`` or the C-API without the need to lose the semantics of a
read-only attribute.
Why not "__attribute_order__"?
------------------------------
@ -178,12 +193,27 @@ Why not 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
``__definition_order__``. Instead, for nearly everyone they would only
be clutter, causing the same extra work for everyone.
be clutter, causing the same extra work (filtering out the dunder
names) for the majority. In cases where a dunder name is significant,
the class definition *could* manually set ``__definition_order__``,
making the common case simpler.
However, dropping dunder names by default may inadvertantly cause
problems for classes that use dunder names unconventionally. In this
case it's better to play it safe and preserve *all* the names from
the class definition.
However, leaving dunder names out of ``__definition_order__`` means
that their place in the definition order would be unrecoverably lost.
Dropping dunder names by default may inadvertantly cause problems for
classes that use dunder names unconventionally. In this case it's
better to play it safe and preserve *all* the names from the class
definition. This isn't a big problem since it is easy to filter out
dunder names::
(name for name in cls.__definition_order__
if not (name.startswith('__') and name.endswith('__')))
In fact, in some application contexts there may be other criteria on
which similar filtering would be applied, such as ignoring any name
starting with "_", leaving out all methods, or including only
descriptors. Ultimately dunder names aren't a special enough case to
be treated exceptionally.
Note that a couple of dunder names (``__name__`` and ``__qualname__``)
are injected by default by the compiler. So they will be included even
@ -220,6 +250,15 @@ We could also also allow an arbitrary iterable for a manually set
all iterables infer a definition order (e.g. ``set``). So we opt in
favor of requiring a tuple.
Why not hide __definition_order__ on non-type objects?
------------------------------------------------------
Python doesn't make much effort to hide class-specific attributes
during lookup on instances of classes. While it may make sense
to consider ``__definition_order__`` a class-only attribute, hidden
during lookup on objects, setting precedent in that regard is
beyond the goals of this PEP.
Why is __definition_order__ even necessary?
-------------------------------------------
@ -270,9 +309,8 @@ 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``.
be minimal. All conforming implementations are expected to set
``__definition_order__`` as described in this PEP.
Open Questions
@ -280,6 +318,10 @@ Open Questions
* What about `__slots__`?
* Allow setting ``__definition_order__`` in ``type()``?
* C-API for setting ``__definition_order__``?
* Drop the "read-only attribute" requirement?
Per Guido: