Ответ
__new__ и __init__ — это два специальных метода, участвующих в создании экземпляра класса, но они выполняют принципиально разные задачи в процессе инстанцирования.
| Метод | Когда вызывается | Задача | Возвращаемое значение | Аналог в других языках |
|---|---|---|---|---|
__new__(cls, ...) |
Первым, в момент создания объекта. | Создать и вернуть новый экземпляр (объект). Это конструктор на уровне класса. Управляет самим процессом выделения памяти. | Должен вернуть новый экземпляр (обычно super().__new__(cls)). Может вернуть объект другого типа. |
Конструктор (new в C#, Java). |
__init__(self, ...) |
Вторым, после __new__, если __new__ вернул экземпляр этого же класса. |
Инициализировать (настроить) созданный объект. Устанавливает начальные значения атрибутов. Это инициализатор. | Ничего не возвращает (None). Изменяет переданный ему объект self. |
Инициализатор (метод __init__ или конструктор с установкой полей). |
Простая аналогия:
__new__— это производство пустого автомобиля на заводе.__init__— это комплектация этого автомобиля: покраска, установка сидений и руля.
Базовый пример последовательности вызовов:
class MyClass:
def __new__(cls, *args, **kwargs):
print(f"__new__ called. Creating instance of {cls.__name__}")
# 1. Создаем экземпляр. Обычно это делает object.__new__
instance = super().__new__(cls)
return instance # Этот объект будет передан в __init__ как `self`
def __init__(self, value):
print(f"__init__ called. Initializing with value={value}")
self.value = value
obj = MyClass(42)
# Вывод:
# __new__ called. Creating instance of MyClass
# __init__ called. Initializing with value=42
Практическое применение __new__ (когда он нужен):
__new__ используется редко, в основном для нетривиального управления созданием объектов:
- Создание неизменяемых (immutable) типов: Так как
__init__может изменить объект, для неизменяемых классов (наследниковtuple,int) логику установки значений нужно поместить в__new__. -
Паттерн Singleton (ограничение числа экземпляров):
class Singleton: _instance = None def __new__(cls): if cls._instance is None: print("Creating the single instance") cls._instance = super().__new__(cls) return cls._instance # Всегда возвращаем один и тот же объект def __init__(self): # Внимание: __init__ будет вызываться каждый раз при вызове Singleton()! print("Singleton __init__ called")
s1 = Singleton() # Создаст экземпляр, вызовет init s2 = Singleton() # Вернет существующий экземпляр, но init вызовется снова! print(s1 is s2) # True
**Важное замечание:** В Python `__init__` вызывается автоматически, если `__new__` вернул объект того же класса. Это может привести к неочевидному повторному вызову `__init__` для уже инициализированного объекта (как в Singleton выше). Поэтому `__new__` и `__init__` нужно использовать согласованно. Видео-ответы
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶