[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.
-eric
---------------------
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
cls.__dict__).
So the key changes are:
* use OrderedDict by default for class definition namespace (e.g. from
type.__prepare__)
* 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):
@classmethod.
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.
[10]
[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
https://www.python.org/dev/peps/pep-3115/
[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
https://mail.python.org/pipermail/python-dev/2013-February/124439.html
[10] Nick: https://mail.python.org/pipermail/python-ideas/2015-March/032254.html
More information about the Python-Dev
mailing list