6

It's documented that the definition order in classes is preserved (see also PEP 520):

If the metaclass has no __prepare__ attribute, then the class namespace is initialised as an empty ordered mapping.

Is the definition order also preserved in module objects?

# foo_bar.py

def foo():
    pass

def bar():
    pass

I've experimented with the module above (also swapping the ordering), and it did seem to be reliable:

>>> import foo_bar
>>> for name in foo_bar.__dict__:
...     if not name.startswith('_'):
...         print(name)
... 
foo
bar

Presumably, the module namespace also uses a compact dict underneath, or perhaps it follows from the fact that the type(foo_bar) is a <class 'module'> that it must also respect definition order, like any other class. However, I'm not sure if this is a feature guaranteed by Python, or just a CPython implementation detail. Are the names in modules required to respect definition ordering?

wim
  • 338,267
  • 99
  • 616
  • 750
  • As far as I know, it's an implementation detail. It might be made an explicit guarantee later, or just an implicit one from the combination of how module-level name definition is specified and how dict order is specified once dict order is actually part of the spec. – user2357112 Mar 15 '17 at 21:39
  • Note that `foo_bar` is not a class. You seem to have gotten mixed up by how `type(foo_bar)` has `class` in the output. The `class` in the output just means that `type(foo_bar)` is a class; it doesn't mean `foo_bar` itself is one. – user2357112 Mar 15 '17 at 21:41
  • No, my suggestion is like this: Class -> instance=Class() -> instance attributes respect ordering because the namespace uses compact dict. ModuleType -> module=ModuleType() -> module attributes respect ordering (?) because namespace uses compact dict (?). – wim Mar 15 '17 at 21:47
  • i.e. A module is "just" an instance of the `ModuleType` class. – wim Mar 15 '17 at 21:47
  • The ordering guarantees haven't been extended to all instances of all classes whose instances have a `__dict__` yet. That's still an implementation detail. – user2357112 Mar 15 '17 at 22:34

1 Answers1

2

Built-in classes, like the module class, don't go through the normal mechanism user-defined classes do* and, as such, don't make use of metaclass.__prepare__. PEP 520 does not apply for them so the guarantees it extends cannot be applied here.

The ordering of the module namespace is currently preserved due to the dictionary being insertion ordered so, like the dictionary itself, is considered an implementation detail.


* User defined classes first go through build_class (the function the LOAD_BUILD_CLASS bytecode loads when you dis a class statement) in bltinmodule.c. This is the only place where __prepare__ is invoked (which returns a PyDict_New from type_prepare if a custom meta with a __prepare__ isn't defined).

wim
  • 338,267
  • 99
  • 616
  • 750
Dimitris Fasarakis Hilliard
  • 150,925
  • 31
  • 268
  • 253
  • What type of storage backend does a module namespace use and where is it created? I have heard it said somewhere that it's a special kind of dict optimized for string keys, but when I checked it in the REPL it seems just to be a normal dict and I was able to setitem with non-string keys no problem. – wim Mar 17 '17 at 15:44
  • I'm pretty sure it's created in the belly of the import mechanism but I'll have to look into that and get back at you @wim. The special kind of dict you're talking about might be [the key-sharing one that exists for instances](http://stackoverflow.com/questions/42419011/why-is-the-dict-of-instances-so-small-in-python-3) but I don't really know if it is also used for modules. – Dimitris Fasarakis Hilliard Mar 17 '17 at 18:18