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

Чем __new__ отличается от __init__?

MiddleООП
Ещё спрашивают так:
  • Когда переопределяют __new__?
Коротко

__new__ — статический метод, создаёт и возвращает экземпляр (вызывается первым). __init__ — инициализирует уже созданный объект и ничего не возвращает. __new__ переопределяют редко: подклассы неизменяемых типов (int, str, tuple), синглтоны и кэши экземпляров, метаклассы.

  • Если __new__ вернул объект не своего класса, __init__ не вызывается
  • Неизменяемый объект нельзя изменить в __init__ — значение задаётся в __new__
  • Вызов: cls.__new__(cls, ...), затем obj.__init__(...)

А ещё Для синглтона проще модуль или функция с lru_cache

Подробно

**Последовательность Cls(args):** метакласс вызывает Cls.__new__(Cls, *args) — он выделяет объект (обычно через super().__new__(cls)) и возвращает его; если результат — экземпляр Cls, вызывается obj.__init__(*args).

Зачем __new__:

  • неизменяемые типы — значение int, str, tuple задаётся при создании; в __init__ его уже не поменять;
  • контроль создания — вернуть существующий экземпляр (кэш, синглтон), объект подкласса (фабрика);
  • метаклассы — __new__ метакласса создаёт класс.

Ловушка синглтона через __new__: даже если __new__ возвращает тот же объект, __init__ вызывается при каждом Cls() и сбрасывает состояние. Для синглтона в Python обычно достаточно модуля — он импортируется один раз.

Пример

class Celsius(float):
    def __new__(cls, value):
        if value < -273.15:
            raise ValueError("ниже абсолютного нуля")
        return super().__new__(cls, value)

t = Celsius(21.5)   # __init__ float тут не помог бы: значение уже задано

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

  • Создание против инициализации.
  • Когда нужен __new__.

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

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

Показать варианты и ответ
  • ✓__new__ создаёт экземпляр, __init__ его настраивает
  • ✗__init__ создаёт и возвращает экземпляр, а __new__ потом настраивает его атрибуты
  • ✗Подкласс str инициализируют, меняя его значение внутри __init__ после создания
  • ✗__init__ обязан возвращать self, иначе конструктор вернёт None вместо объекта

Разбор темы

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

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

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

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

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