[Python-Dev] PEP: Ordered Class Definition Namespace (original) (raw)

Eric Snow ericsnowcurrently at gmail.com
Tue Jun 7 13:51:52 EDT 2016


Hi all,

Following discussion a few years back (and rough approval from Guido [1]), I started work on using OrderedDict for the class definition namespace by default. The bulk of the effort lay in implementing OrderedDict in C, which I got landed just in time for 3.5. The remaining work was quite minimal and the actual change is quite small.

My intention was to land the patch soon, having gone through code review during PyCon. However, Nick pointed out to me the benefit of having a concrete point of reference for the change, as well as making sure it isn't a problem for other implementations. So in that spirit, here's a PEP for the change. Feedback is welcome, particularly from from other implementors.

-eric

[1] https://mail.python.org/pipermail/python-ideas/2013-February/019704.html

==================================================

PEP: XXX Title: Ordered Class Definition Namespace Version: RevisionRevisionRevision Last-Modified: DateDateDate Author: Eric Snow <ericsnowcurrently at gmail.com> Status: Draft Type: Standards Track Content-Type: text/x-rst Created: 4-Jun-2016 Python-Version: 3.6 Post-History: 7-Jun-2016

Abstract

This PEP changes the default class definition namespace to OrderedDict. Furthermore, the order in which the attributes are defined in each class body will now be preserved in type.__definition_order__. This allows introspection of the original definition order, e.g. by class decorators.

Note: just to be clear, this PEP is not about changing type.__dict__ to OrderedDict.

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 following code demonstrates roughly equivalent semantics::

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() if (!k.startswith('') or !k.endswith('')))

Note that [pep487_] proposes a similar solution, albeit as part of a broader proposal.

Compatibility

This PEP does not break backward compatibility, except in the case that someone relies strictly on dicts as the class definition namespace. This shouldn't be a problem.

Changes

In addition to the class syntax, the following expose the new behavior:

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__toNone``.

Implementation

The implementation is found in the tracker. [impl_]

Alternatives

type.dict as OrderedDict

Instead of storing the definition order in __definition_order__, the now-ordered definition namespace could be copied into a new OrderedDict. This would mostly provide the same semantics.

However, using OrderedDict for type,__dict__ would obscure the 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)

.. [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.



More information about the Python-Dev mailing list