sorted(__all__ + deprecated_names) version assumes that
contains all your module’s public names, except for deprecated names. If
you haven’t defined
__all__, or if it is out of date, then it will
miss some things.
[*globals().keys(), *deprecated_names] version grabs everything
from the module namespace, whether you intend them to be listed or not,
including global variables.
What’s the difference? Suppose your module looks like this:
__all__ = ['spam', 'eggs', 'Cheese', 'foo']
# Public names
spam = 'spam, eggs, spam, spam and spam on toast'
storage = 1
# Private names
# Incidental variables
for i in range(3):
# Deprecated names
deprecated = ['bar',]
__all__ version will give you a dir() of:
spam, eggs, Cheese, foo, bar
while the version with globals will give you a dir() of:
__all__, sys, spam, eggs, Cheese, _private, i, deprecated, bar, __dir__
plus some additional internal details of modules:
__builtins__, __cached__, __doc__, __file__, __loader__, __name__,
(intentionally not sorting the output but leaving it in input order).
Notice that the global variable “storage” doesn’t show up. That’s
because I haven’t run
eggs(). Once I run
eggs(), the second version
of dir will change to include it.
In the first case, because your
__all__ wrongly includes the obsolete
name “foo”, it still shows up in dir(); in the second case you get a
bunch of stuff you probably don’t want to see, like imports and dunders.
Personally, I strongly dislike the default output of
dir() and I run a
monkey-patched version which strips out all those dunder names unless I
explicitly ask for them. If I were to take the time and effort to define
__dir__ for my module, the last thing I would want to do is
fill it with module dunders and private names.
But it’s your module, and you get to choose whatever behaviour makes the
most sense to you.