Python dir(): как узнать атрибуты объекта
Функция dir() в Python возвращает отсортированный список имен, доступных у объекта: его атрибутов и методов. Без аргумента она показывает имена текущей области видимости. Ниже разобрано, как пользоваться dir() для изучения незнакомых модулей и классов, как убрать из результата служебные имена и чем эта функция отличается от vars(), help() и модуля inspect.

Содержание статьи
Синтаксис и возвращаемое значение
Функция встроенная, импортировать ее не нужно. Она принимает один необязательный аргумент - любой объект Python.
dir() # имена текущей области видимости
dir(obj) # атрибуты объекта objРезультат всегда список строк, отсортированный по алфавиту. В нем только имена, а не значения: чтобы получить сам атрибут, имя передают в getattr(). Документация прямо говорит, что dir() предназначена в первую очередь для интерактивной работы и старается показать полезный набор имен, а не исчерпывающий. Поэтому строить на ее выводе логику программы не рекомендуется.
Вызов без аргумента
Без аргумента dir() выводит имена, определенные в текущей области. На уровне модуля это глобальные переменные, функции и импортированные модули, внутри функции - только ее локальные переменные.
import math
limit = 10
def show():
a, b = 1, 2
print(dir()) # ['a', 'b']
show()
print([n for n in dir() if not n.startswith('__')])
# ['limit', 'math', 'show']Такой вызов помогает в консоли вспомнить, какие переменные уже созданы, или проверить, что модуль действительно импортирован под нужным именем. Служебные имена вида __name__ и __builtins__ тоже попадают в список, поэтому их удобно отсекать проверкой startswith('__').
Атрибуты встроенных типов и модулей
Основное применение dir() - быстро посмотреть, что умеет объект, не открывая документацию. Если передать список, строку или словарь, в результате окажутся все их методы.
public = [m for m in dir(list) if not m.startswith('_')]
print(public)
# ['append', 'clear', 'copy', 'count', 'extend', 'index',
# 'insert', 'pop', 'remove', 'reverse', 'sort']
print('split' in dir(str)) # TrueПередавать можно как сам тип (list), так и конкретный экземпляр ([1, 2]): у встроенных типов результат совпадет. Подробно все методы списка описаны в статье о методах списка.
С модулями dir() работает так же и выручает, когда нужно найти функцию по части названия.
import math, os
print([n for n in dir(math) if 'log' in n])
# ['log', 'log10', 'log1p', 'log2']
print([n for n in dir(os.path) if n.startswith('is')])
# isabs, isdir, isfile, islink, ismount и другиеНабор функций в некоторых модулях зависит от версии Python и операционной системы, поэтому вывод на вашем компьютере может немного отличаться.
dir() для собственных классов и объектов
Для экземпляра класса dir() собирает имена из трех мест: атрибуты самого объекта, атрибуты его класса и атрибуты всех родительских классов. Поэтому в выводе видны и данные экземпляра, и методы, и унаследованные от object служебные методы.
class User:
role = 'guest'
def __init__(self, name):
self.name = name
def greet(self):
return f'Привет, {self.name}'
u = User('Анна')
print([n for n in dir(u) if not n.startswith('__')])
# ['greet', 'name', 'role']
print([n for n in dir(User) if not n.startswith('__')])
# ['greet', 'role'] - name появляется только у экземпляраЧтобы отличить методы от данных, имя проверяют через callable(getattr(obj, name)). Как работает получение атрибута по строке, разобрано в статье о функции getattr.
for name in dir(u):
if name.startswith('_'):
continue
value = getattr(u, name)
kind = 'метод' if callable(value) else 'данные'
print(f'{name:6} {kind}')
# greet метод
# name данные
# role данныеМетод __dir__ и управление выводом
Если в классе определить метод __dir__, dir() вызовет его и вернет отсортированный результат. Это полезно, когда атрибуты создаются динамически через __getattr__ и иначе не были бы видны, например у обертки над JSON-конфигом.
class Config:
def __init__(self, data):
self._data = data
def __getattr__(self, key):
try:
return self._data[key]
except KeyError:
raise AttributeError(key) from None
def __dir__(self):
return list(self._data) + ['_data']
cfg = Config({'port': 8080, 'host': 'localhost'})
print(dir(cfg)) # ['_data', 'host', 'port']
print(cfg.port) # 8080Метод должен вернуть последовательность строк, а сортировку выполнит сама dir(). Автодополнение в IPython и Jupyter тоже использует __dir__, поэтому после такой доработки редактор начнет подсказывать ключи конфига. Об остальных специальных методах рассказано в материале о магических методах. Начиная с Python 3.7, функцию __dir__ можно определить и на уровне модуля, чтобы скрыть из вывода служебные имена.
Чем dir() отличается от vars(), help() и inspect
Для изучения объектов в Python есть несколько инструментов, и каждый отвечает на свой вопрос.
| Инструмент | Что возвращает | Когда использовать |
|---|---|---|
| dir(obj) | Список имен, включая унаследованные | Понять, какие атрибуты и методы доступны |
| vars(obj) | Словарь __dict__: только собственные атрибуты с значениями | Посмотреть данные конкретного экземпляра |
| help(obj) | Текстовая справка с описанием и сигнатурами | Узнать, как вызывать функцию или метод |
| inspect.getmembers(obj) | Список пар (имя, значение), можно фильтровать по типу | Программно перебрать методы или функции |
import inspect
print(vars(u)) # {'name': 'Анна'}
methods = inspect.getmembers(User, predicate=inspect.isfunction)
print([name for name, _ in methods]) # ['__init__', 'greet']Функция vars() выдаст ошибку TypeError для объектов без __dict__, например для чисел или экземпляров класса со __slots__, а dir() работает с любым объектом. Описание остальных инструментов интроспекции есть в обзоре встроенных функций Python и в официальной документации.
Частые вопросы
Ответы на типичные вопросы о функции dir().
Почему dir() показывает не все атрибуты?
Функция не включает атрибуты метакласса для классов и имена, которые создаются на лету через __getattr__. Если такие атрибуты важны, опишите их в методе __dir__.
Как вывести только методы объекта?
Отфильтруйте список: [n for n in dir(obj) if callable(getattr(obj, n)) and not n.startswith('_')].
Как вывести список вертикально, по одному имени в строке?
Склейте элементы переносом строки: print('\n'.join(dir(obj))).
Чем dir() отличается от __dict__?
__dict__ содержит только собственные атрибуты объекта со значениями, а dir() возвращает имена из объекта, его класса и всех родителей, без значений.