[Python-Dev] Preserving the definition order of class namespaces.

Eric Snow ericsnowcurrently at gmail.com
Sun May 24 03:15:35 CEST 2015

tl;dr Are there any objections to making making the default
cls.__prepare__ return OrderedDict instead of dict (and preserve that
order in a list on the class)?

A couple years ago [1][2] I proposed making class definition
namespaces use OrderedDict by default.  Said Guido [3]:

    I'm fine with doing this by default for a class namespace; the type of
    cls.__dict__ is already a non-dict (it's a proxy) and it's unlikely to
    have 100,000 entries.

It turns out making cls.__dict__ an OrderedDict isn't reasonably
tractable (due to the concrete API v. subclasses), but really that
isn't what I was looking for anyway.

Regardless, since it's been a while I just want to run the proposal by
the group again.  I'm hopeful about landing my C implementation of
OrderedDict [4] in the next few days.  Also, I have a patch up [5]
that implements using OrderedDict for class definitions.  So mostly I
just want to double check that I'm still good to go.

Just to be clear on what I'm proposing specifically, I've summed it up below.



Currently if you want to preserve the order of a class definition you
have to use a metaclass with a __prepare__ method (see PEP 3115).
However, as that PEP points out [6], the common case for __prepare__
is to use OrderedDict.  I'm proposing that we return OrderedDict() by
default from __prepare__.  Considering the common case, we should also
expose that definition order on the class afterward since otherwise
the extra information from the class definition namespace is discarded
(type.__new__ copies it into a dict which is then used for

So the key changes are:

* use OrderedDict by default for class definition namespace (e.g. from
* expose that definition order as cls.__definition_order__ (a list)

(Note that I will not be changing the actual type of cls.__dict__
(i.e. tp_dict) which will remain a dict.)

The effect of the change would be that the following are basically
equivalent (relative to the the definition namespace):

    class Meta(type):
        def __prepare__(meta, *args, **kwargs):
            return OrderedDict()

    class SpamOld(metaclass=Meta):
        a = 1
        b = 2
        c = 3
        __definition_order__ = list(locals())

    class SpamNew:
        a = 1
        b = 2
        c = 3

    assert SpamOld.__definition__order == SpamNew.__definition_order__

The key differences are:

* for SpamNew you don't need to use a metaclass [7][8]
* for SpamNew you don't need to rely on the behavior of locals()
* for SpamNew the class definition isn't cluttered with extra
boilerplate for __definition_order__
* class decorators that care about definition order [9] don't have to
require that classes like SpamNew manually preserve that order somehow

The patch for the change is pretty minimal. [5]

Also, Nick Coghlan recently expressed that he favored using
OrderedDict by default over the alternative presented by PEP 422/487.

[1] https://mail.python.org/pipermail/python-ideas/2013-February/019690.html
[2] https://mail.python.org/pipermail/python-dev/2013-June/127103.html
[3] Guido: https://mail.python.org/pipermail/python-ideas/2013-February/019704.html
[4] http://bugs.python.org/issue16991
[5] http://bugs.python.org/issue24254
[6] see the "Alternate Proposals" section of
[7] PEPs 422 and 487 relatedly focus on the benefits of reducing the
need to use metaclasses
[8] https://mail.python.org/pipermail/python-ideas/2013-February/019706.html
[9] see "Key points" on
[10] Nick: https://mail.python.org/pipermail/python-ideas/2015-March/032254.html

More information about the Python-Dev mailing list