__init__ против __new__

Каверзный вопрос для продвинутых: какой из двух методов создаёт объект, а какой инициализирует.

__new__ создаёт и возвращает новый объект (конструктор). __init__ настраивает уже созданный объект (инициализатор).

Вопрос: в чём разница?

Чёткий ответ. При вызове MyClass(...) сначала отрабатывает __new__ — он выделяет память и возвращает экземпляр. Затем на этом экземпляре вызывается __init__, который задаёт атрибуты. В 99% случаев вы пишете только __init__.

class Demo:
    def __new__(cls, *args, **kwargs):
        print("1. __new__: создаём объект")
        return super().__new__(cls)

    def __init__(self, value):
        print("2. __init__: настраиваем объект")
        self.value = value

d = Demo(42)
print("3. value =", d.value)

Вывод:

1. __new__: создаём объект
2. __init__: настраиваем объект
3. value = 42

Порядок чёткий: сначала создание, потом инициализация. __new__ получает класс cls, __init__ — уже готовый self.

Когда нужен __new__

Переопределять __new__ приходится редко: при наследовании от неизменяемых типов (int, str, tuple) или для паттернов вроде синглтона, где нужно контролировать само создание объекта.

class Singleton:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance      # всегда один и тот же объект

a = Singleton()
b = Singleton()
print("один объект:", a is b)

Вывод:

один объект: True

Важная деталь про возврат

__new__ обязан вернуть экземпляр класса, иначе __init__ не вызовется. __init__ же должен возвращать None — возврат другого значения вызовет ошибку.

МетодРольПервый аргумент
__new__создаёт объектcls (класс)
__init__настраивает объектself (экземпляр)

Итог

  • __new__ создаёт объект и возвращает его; __init__ инициализирует уже созданный.
  • Сначала вызывается __new__, потом __init__.
  • Переопределяют __new__ редко: наследование от immutable-типов, синглтон.
Проверьте себя
1. Какой метод вызывается первым при MyClass(...)?
A__init__
B__new__
C__call__
D__create__
2. Что должен вернуть __new__?
ANone
BЭкземпляр класса
CИмя класса
DСловарь атрибутов
3. Когда обычно переопределяют __new__?
AВсегда вместо __init__
BДля задания обычных атрибутов
CПри наследовании от неизменяемых типов или для синглтона
DДля печати объекта
Поддержать проект