Custom __dir __ () returns a list of attributes sorted alphabetically

I have a typical implementation __dir__in the base class that should return a list of all user-defined attributes __slots__. This works, in general, but it seems to do the result sortby the result before it returns, although I did not program it (I need the attributes so that the same order is assigned).

Example:

class A:
    __slots__ = ['b', 'a']

    def __dir__(self):
        slot_attrs = []
        for parent_class in reversed(type(self).__mro__[:-1]):
            for attr in parent_class.__slots__:
                slot_attrs.append(attr)
        for attr in self.__slots__:
            slot_attrs.append(attr)
        return slot_attrs


class B(A):
    __slots__ = ['c', 'd']
    pass


class C(B):
    __slots__ = []
    pass


class D:
    __slots__ = ['b', 'a']

    def slots(self):
        slot_attrs = []
        for parent_class in reversed(type(self).__mro__[:-1]):
            for attr in parent_class.__slots__:
                slot_attrs.append(attr)
        for attr in self.__slots__:
            slot_attrs.append(attr)
        return slot_attrs


class E(D):
    __slots__ = ['c', 'd']
    pass


class F(E):
    pass

The conclusion for slots()and __dir__()should be, imo, identical.

but instead this happens:

>>>c = C()
>>>f = F()

>>>print(dir(c))
['a', 'b', 'c', 'd']
>>>print(f.slots())
['b', 'a', 'c', 'd', 'c', 'd', 'c', 'd']

, dir() - . , - , , - , __dir__.

. , dir - , , set, , , slots() .

) , , ), dir .

?

:
- __mro__ , , , . :.

>>>F.__mro__
(<class '__main__.F'>, <class '__main__.E'>, <class '__main__.D'>, <class 'object'>)

2:
. , , :

>>Couldn't __dir__ also be allowed to return a tuple?
no, because tuples are not sortable, and i don't want to 
over complicate the c-side code of PyObject_Dir. 
having __dir__ returning only a list is equivalent to 
__repr__ returning only strings.

, C, __dir__.

3:
python bug tracker. , . , , backburner ( ), dir() is, afaik, IDLE ..

+4
1

Pugon tracker:

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'>
+1

Source: https://habr.com/ru/post/1687773/


All Articles