__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-типов, синглтон.