Make __dict__ return items in the order they were defined in

I wanted to get a list of all the functions in a module and run them in the order they are written. This is not trivial to do because inspect.getmembers will “return all the members of an object in a list of (name, value) pairs sorted by name”. The sorting happens on the last line of that function, so I tried defining my own getmembers with that line removed but that didn’t work because it uses dir() and __dict__ which also don’t return properties in the order they are defined.

dicts are ordered now so it would make sense for those builtins to try and preserve a sensible order, which is obviously the order they were populated in.

Getting a list of module members in the order they are defined in was also asked about on Stack Overflow 10 years ago where the suggestion is to recover the order by looking at .__code__.co_firstlineno but that doesn’t work for things that aren’t functions.

dir() is documented as returning a convenient, “interesting” list of
attributes, with no guarantee of returning all attributes.

You probably should use vars(module) rather than module.__dict__.
Not only does it look nicer, but its good practice to not touch dunders
directly.

As far as I can see, just iterating over vars(module).items() should
do exactly what you want.

1 Like

I realize now that __dict__ already contains things in the order they were defined. I was looking at it using pprint.pprint which sorts the keys alphabetically… Thanks!

Is the order of __dict__ documented anywhere? Can it be relied on? Is it an implementation detail? I don’t see it mention in https://docs.python.org/3/library/functions.html#dir or https://docs.python.org/3/library/stdtypes.html#object.__dict__

A module __dict__ is just a regular dict, so it obeys the exact same
constraints and features as any other dict.

Dicts now preserve insertion order. There is no promise made that
modules will insert their globals in any specific order, but whatever
order their globals are created will be reflected in the order of keys
in their __dict__.

Meta: Why was this post flagged? It belongs in Users, not Ideas, but after reading it I don’t see a reason why it should be flagged and hidden. Maybe there are some readers who are a little too quick in flagging posts from newbies?

1 Like

FWIW, there is a variant, pprint.pp() that preserves order.

This works for what I want to do (get functions and variables in a module in order of definition), but it doesn’t work for class properties, which is what the person asking that question on Stack overflow wanted, so I would change my idea to “make dir() return items in the order they were defined in instead of sorting its output”. It would be useful to have a inspect.getmembers (which uses dir()) that returns things in a useful order, instead of destroying that information. If you want to sort the output, you’d have to call sorted yourself.

I self-flagged it and asked for the whole thread to be deleted, but just the first post got hidden.

Iterating over the class dict seems to work for me:


>>> class MyClass:
...     one = 1
...     two = 2
...     three = 3
...     four = 4
...     five = 5
... 
>>> for key, value in vars(MyClass).items():
...     print(key, value)
... 
__module__ __main__
one 1
two 2
three 3
four 4
five 5
__dict__ <attribute '__dict__' of 'MyClass' objects>
__weakref__ <attribute '__weakref__' of 'MyClass' objects>
__doc__ None

Doesn’t seem to be sorted or in arbitrary order to me. Of course I can’t
tell about the order the dunders are added, but the regular attributes
seem to have kept insertion order.

Unfortunately that doesn’t help if your class has __slots__, but for
that you can just check for the existence of MyClass.__slots__ and
iterate over that.

Why are you asking for the thread to be deleted? It seems to be a
perfctly good thread that may be useful to others.