Чем __new__ отличается от __init__?
- Когда переопределяют __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 вместо объекта
Разбор темы
- Модель данных — создание объектов, атрибуты и дескрипторы
__new__ и __init__, согласование __eq__ и __hash__, __getattr__ и __getattribute__, дескрипторы и __slots__.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.