Update PEP 520 per python-dev feedback.
This commit is contained in:
parent
c7adf1141c
commit
e901e81295
84
pep-0520.txt
84
pep-0520.txt
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue