This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Unexpected behaviour of `dir()` after implementation of __dir__
Type: behavior Stage: resolved
Components: Versions: Python 3.5
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: christian.heimes, nlsdfnbch
Priority: normal Keywords:

Created on 2017-10-19 07:48 by nlsdfnbch, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (4)
msg304606 - (view) Author: Nils Diefenbach (nlsdfnbch) Date: 2017-10-19 07:48
When defining a custom __dir__ method in a class, calling dir() on
said class still sorts the output. This is, imo, unexpected behaviour, especially if the order of output was specified in __dir__ and is somehow relevant.

Example and more detail here
https://stackoverflow.com/questions/46824459/custom-dir-returns-list-of-attributes-sorted-alphabetically
msg304608 - (view) Author: Christian Heimes (christian.heimes) * (Python committer) Date: 2017-10-19 08:03
dir() and __dir__ work as designed and documented:

https://docs.python.org/3/reference/datamodel.html?highlight=__dir__#object.__dir__

Called when dir() is called on the object. A sequence must be returned. dir() converts the returned sequence to a list and sorts it
msg304609 - (view) Author: Nils Diefenbach (nlsdfnbch) Date: 2017-10-19 08:27
Alright. Are there any other magic methods that do some post-processing on a custom implementation of them ? 

I couldn't think of one, which is why this behaviour appeared odd to me.
msg304610 - (view) Author: Christian Heimes (christian.heimes) * (Python committer) Date: 2017-10-19 08:35
https://docs.python.org/3/library/functions.html#dir also states that "The resulting list is sorted alphabetically." The section has an example where __dir__ returns an unsorted list but dir() returns a sorted list:

>>> class Shape:
...     def __dir__(self):
...         return ['area', 'perimeter', 'location']
>>> s = Shape()
>>> dir(s)
['area', 'location', 'perimeter']

Since the primary purpose of dir() is convenient use for humans, sorting makes perfectly sense. If you need tight control over order of values, you should make your object iterable instead or provide another method.

Several dunder methods perform some sort of post-processing or post-check:

>>> class Example:
...     def __bool__(self): return 2
... 
>>> bool(Example())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __bool__ should return bool, returned int

>>> class MyInt(int):
...     pass
... 
>>> type(MyInt(1))
<class '__main__.MyInt'>
>>> class Example:
...     def __int__(self):
...         return MyInt(1)
... 
>>> int(Example())
1
>>> type(int(Example()))
<class 'int'>
History
Date User Action Args
2022-04-11 14:58:53adminsetgithub: 75997
2017-10-19 08:35:11christian.heimessetstatus: open -> closed

messages: + msg304610
stage: resolved
2017-10-19 08:27:27nlsdfnbchsetstatus: pending -> open

messages: + msg304609
2017-10-19 08:03:45christian.heimessetstatus: open -> pending

nosy: + christian.heimes
messages: + msg304608

resolution: not a bug
2017-10-19 07:48:26nlsdfnbchcreate