← Назад к вопросам

В чем разница между init и dir?

1.2 Junior🔥 111 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между init и dir

Это два фундаментально разных магических метода в Python, которые выполняют совершенно разные роли в жизненном цикле объекта и его отражении (introspection).

init — Инициализатор объекта

init вызывается сразу после создания объекта (после new) и служит для инициализации состояния экземпляра:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.email = None

person = Person("Alice", 30)  # Здесь вызывается __init__
print(person.name)  # Alice

Характеристики init:

  • Вызывается один раз при создании экземпляра
  • Инициализирует атрибуты объекта
  • Не должен возвращать значение (кроме None)
  • Позволяет установить начальное состояние
  • Может валидировать входные параметры

dir — Список атрибутов

dir возвращает список доступных атрибутов и методов объекта. Вызывается встроенной функцией dir():

class Person:
    class_attr = "class attribute"
    
    def __init__(self, name):
        self.name = name
        self._private = "private"
    
    def public_method(self):
        pass
    
    def __dir__(self):
        return [name, class_attr, public_method]

person = Person("Bob")
print(dir(person))  # [name, class_attr, public_method]

Характеристики dir:

  • Вызывается функцией dir() для интроспекции
  • Возвращает список строк (имена атрибутов)
  • Позволяет контролировать видимость атрибутов
  • Полезна для скрытия внутренних деталей
  • Влияет на автодополнение в IDE

Практическое сравнение

class DataProcessor:
    def __init__(self, data):
        # Выполняется ОДИН РАЗ при создании
        self.data = data
        self._cache = {}
        self._processed = False
    
    def __dir__(self):
        # Выполняется при вызове dir()
        # Скрываем внутренние атрибуты из публичного API
        public_attrs = [data, process, get_result]
        return sorted(public_attrs)
    
    def process(self):
        pass
    
    def get_result(self):
        pass

# Создание объекта вызывает __init__
processor = DataProcessor([1, 2, 3])

# Проверка доступных атрибутов вызывает __dir__
print(dir(processor))
# [data, get_result, process]
# Обратите внимание: _cache и _processed скрыты!

Когда они вызываются

МетодКогда вызываетсяЗачемВозвращает
initПри создании объектаИнициализация состоянияNone
dirПри вызове dir(obj)Интроспекцияlist[str]

Взаимодействие с IDE и REPL

init — не видно IDE (IDE не может угадать, какие атрибуты будут созданы):

class User:
    def __init__(self, username):
        self.username = username
        self.profile = None

# IDE НЕ будет подсказывать .username и .profile без аннотаций типов

dir и type hints вместе — дают лучшую IDE поддержку:

from typing import Any

class User:
    username: str
    profile: dict[str, Any] | None
    
    def __init__(self, username: str):
        self.username = username
        self.profile = None
    
    def __dir__(self) -> list[str]:
        return [username, profile, get_profile]

# Теперь IDE знает о всех атрибутах!

Практическое применение dir

class APIClient:
    def __init__(self, token):
        self.token = token
        self._session = None
        self._retry_count = 3
    
    def __dir__(self):
        # Публичный API клиента
        return [get, post, put, delete, token]
    
    def get(self, url):
        pass
    
    def post(self, url, data):
        pass

client = APIClient("secret-token")
print(dir(client))
# [delete, get, post, put, token]
# _session и _retry_count скрыты от пользователей

Резюме

  • init — конструктор, инициализирует состояние объекта один раз
  • dir — рефлексия, контролирует видимость атрибутов при интроспекции
  • Они вызываются в разные времена и для разных целей
  • init необходимо для работы объекта
  • dir опционально, но улучшает DX и безопасность API