В чем разница между dir() и __dir__?

в python какая разница между функцией dir() и атрибутом __dir__ в python?

>>> 2 .__dir__()
['__divmod__', 'real', '__rxor__', '__floor__', '__hash__', '__index__', '__lt__', '__ceil__', '__repr__', '__reduce_ex__', '__rpow__', '__rand__', '__truediv__', '__subclasshook__', '__doc__', '__radd__', '__or__', '__pow__', '__trunc__', '__rrshift__', '__delattr__', '__reduce__', '__rlshift__', 'conjugate', '__xor__', '__rtruediv__', '__rfloordiv__', '__ge__', '__setattr__', '__class__', 'bit_length', '__neg__', '__mod__', '__int__', '__pos__', 'from_bytes', '__format__', '__rmul__', '__lshift__', '__rsub__', '__new__', '__add__', '__floordiv__', 'imag', 'to_bytes', 'numerator', '__dir__', '__abs__', '__init__', '__sizeof__', '__getnewargs__', '__getattribute__', '__invert__', '__gt__', '__rshift__', '__ne__', '__rdivmod__', '__mul__', '__and__', '__sub__', '__rmod__', '__round__', '__ror__', '__le__', '__eq__', '__float__', '__bool__', '__str__', 'denominator']
>>> dir(2)
['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']

Ответ 1

dir вызывает __dir__ внутренне:

In [1]: class Hello():
   ...:     def __dir__(self):
   ...:         return [1,2,3]
   ...:     

In [2]: dir(Hello())
Out[2]: [1, 2, 3]

Ответ 2

Документы объясняют это:

Если у объекта есть метод с именем __dir __(), этот метод будет вызван и должен вернуть список атрибутов. Это позволяет объектам, которые реализуют пользовательскую функцию __getattr __() или __getattribute __(), настраивать способ, которым dir() сообщает свои атрибуты.

Если объект не предоставляет __dir __(), функция старается собрать информацию из атрибута __dict__ объектов, если он определен, и из объекта своего типа. Результирующий список не обязательно является полным и может быть неточным, если объект имеет собственный __getattr __().

Ответ 3

dir вызывает метод __dir__, если он присутствует, из документация python:

dir ([object]) ¶ Без аргументов верните список имен в текущий локальный охват. С аргументом попытайтесь вернуть список действительные атрибуты для этого объекта.

Если объект имеет метод с именем __dir__(), этот метод будет вызываться и должен возвращать список атрибутов. Это позволяет объектам, которые реализовать пользовательскую функцию __getattr__() или __getattribute__() для настроить способ dir() сообщить свои атрибуты.

Если объект не предоставляет __dir__(), функция пытается изо всех сил для сбора информации из атрибута __dict__ объектов, если и от объекта своего типа. Полученный список не обязательно завершена и может быть неточной, когда объект имеет пользовательский __getattr__().

Ответ 4

Стоит отметить, что __dir__ для многих объектов нельзя настроить, поэтому, если вы вызываете его напрямую, нет возможности разместить там прокладку/обертку.

Легко заменить встроенный dir и дать ему некоторые специальные полномочия, если вам нужно. Трюки, подобные этому, могут быть очень полезны при отладке.