[Python-Dev] PEP 520: Preserving Class Attribute Definition Order (round 5)
ncoghlan at gmail.com
Fri Jun 24 18:37:55 EDT 2016
This version looks fine to me.
On 24 June 2016 at 14:52, Eric Snow <ericsnowcurrently at gmail.com> wrote:
> When a class is defined using a ``class`` statement, the class body
> is executed within a namespace. Currently that namespace defaults to
> ``dict``. If the metaclass defines ``__prepare__()`` then the result
> of calling it is used for the class definition namespace.
> After the execution completes, the definition namespace namespace is
> copied into new ``dict``. Then 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.
> The class attribute definition order is represented by the insertion
> order of names in the *definition* namespace. Thus, we can have
> 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).
The definition order question has been dropped from PEP 487, so this
cross-reference doesn't really make sense any more :)
> Part 2:
> * the default class *definition* namespace is now ``OrderdDict``
> The following code demonstrates roughly equivalent semantics for the
> default behavior::
> class Meta(type):
> def __prepare__(cls, *args, **kwargs):
> return OrderedDict()
> class Spam(metaclass=Meta):
> ham = None
> eggs = 5
> __definition_order__ = tuple(locals())
I'd characterise this section at the language definition level as the
default class definition namespace now being *permitted* to be an
OrderedDict. For implementations where dict is ordered by default,
there's no requirement to switch specifically to
> 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 the ability to set ``__definition_order__`` manually allows
> a dynamically created class (e.g. Cython, ``type()``) to still have
> ``__definition_order__`` properly set.
This paragraph is a little confusing, since "set
``__definition_order__`` manually" is ambiguous.
"supply an explicit ``__definition_order__`` via the class namespace"
might be clearer.
> 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.
> 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.
> Note that a couple of dunder names (``__name__`` and ``__qualname__``)
> are injected by default by the compiler. So they will be included even
> though they are not strictly part of the class definition body.
I realised there's another important reason for doing it this way by
default: it's *really easy* to write a "skip_dunder_names" filter that
leaves out dunder names from an arbitrary interable of strings. It's
flatout *impossible* to restore the dunder attribute order if the
class definition process throws it away.
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
More information about the Python-Dev