Получить доступ

Что такое self и __init__ в классе?

JuniorООП
Ещё спрашивают так:
  • Зачем нужен self?
  • Является ли __init__ конструктором?
  • Чем атрибут класса отличается от атрибута экземпляра?
Коротко

self — ссылка на текущий экземпляр, Python передаёт её в метод первым аргументом.

  • __init__ — инициализатор: заполняет уже созданный объект
  • Создаёт объект __new__, его переопределяют редко

А ещё Атрибуты класса общие для всех экземпляров — осторожно с изменяемыми

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Метод — функция, объявленная в классе. При вызове obj.method(1) Python фактически вызывает Class.method(obj, 1): экземпляр передаётся первым аргументом. По соглашению его называют self. Через self метод читает и пишет атрибуты конкретного объекта.

Создание объекта User("Аня") идёт в два шага:

  1. __new__ создаёт пустой объект нужного класса;
  2. __init__ получает этот объект как self и заполняет атрибуты.

Поэтому __init__ точнее называть инициализатором. __new__ переопределяют, когда нужно управлять созданием: неизменяемые типы (наследники int, tuple), синглтоны.

Атрибуты класса и экземпляра. Переменная в теле класса — общая для всех экземпляров. Переменная через self.x = ... — своя у каждого. Если атрибут класса — список, и экземпляры его меняют, изменения увидят все.

Для простых классов-хранилищ данных удобен @dataclass: он сам генерирует __init__, __repr__ и __eq__.

Пример

class User:
    count = 0                  # атрибут класса — общий

    def __init__(self, name):
        self.name = name       # атрибут экземпляра — свой
        User.count += 1

    def greet(self):
        return f"Привет, {self.name}"

u = User("Аня")
u.greet()             # то же, что User.greet(u)

class Bad:
    tags = []          # один список на всех!

from dataclasses import dataclass, field

@dataclass
class Good:
    name: str
    tags: list = field(default_factory=list)

Что хотят услышать

  • self как явно передаваемый экземпляр, эквивалентность obj.m() и Class.m(obj).
  • __init__ инициализирует, __new__ создаёт.
  • Разница атрибутов класса и экземпляра, ловушка с изменяемым атрибутом класса.
  • Знание dataclass — плюс.

Частые ошибки

  • Называть __init__ конструктором без оговорки.
  • Объявить список в теле класса вместо __init__.

Что спросят дальше

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем