Вопрос с собеседования · Python

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

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

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

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

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

Подробно

Метод — функция, объявленная в классе. При вызове 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__.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✗Атрибуты класса копируются в каждый экземпляр отдельно, поэтому изменяемый атрибут класса у всех свой
  • ✗self — ключевое слово языка, его нельзя назвать иначе
  • ✗__init__ создаёт объект и возвращает его
  • ✓self — ссылка на текущий экземпляр (первый аргумент); __init__ настраивает уже созданный объект

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

Разбор темы

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

Партнёр платформы

Разбор собеседования с sotto

После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.

Разбор собеседования