[Python-Dev] Preserving the definition order of class namespaces.
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  I proposed making class definition
namespaces use OrderedDict by default. Said Guido :
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  in the next few days. Also, I have a patch up 
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 , 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):
def __prepare__(meta, *args, **kwargs):
a = 1
b = 2
c = 3
__definition_order__ = list(locals())
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 
* 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  don't have to
require that classes like SpamNew manually preserve that order somehow
The patch for the change is pretty minimal. 
Also, Nick Coghlan recently expressed that he favored using
OrderedDict by default over the alternative presented by PEP 422/487.
 Guido: https://mail.python.org/pipermail/python-ideas/2013-February/019704.html
 see the "Alternate Proposals" section of
 PEPs 422 and 487 relatedly focus on the benefits of reducing the
need to use metaclasses
 see "Key points" on
 Nick: https://mail.python.org/pipermail/python-ideas/2015-March/032254.html
More information about the Python-Dev