Ответ
Методы __new__
и __init__
— это два ключевых этапа в жизненном цикле создания объекта в Python, но они выполняют принципиально разные задачи.
Ключевое различие: __new__
создает экземпляр, а __init__
его инициализирует (настраивает).
__new__(cls, ...)
- Роль: Создание (construction) объекта. Отвечает за выделение памяти под новый экземпляр.
- Вызывается: Первым, до
__init__
. - Тип: Статический метод (хотя и не требует декоратора
@staticmethod
), первым аргументом принимает классcls
. - Возвращаемое значение: Должен вернуть новый экземпляр класса. Если он этого не сделает,
__init__
не будет вызван.
__init__(self, ...)
- Роль: Инициализация (initialization) объекта. Заполняет атрибуты уже созданного экземпляра.
- Вызывается: Вторым, после
__new__
. - Тип: Метод экземпляра, первым аргументом принимает созданный экземпляр
self
. - Возвращаемое значение: Ничего не возвращает (
None
).
Пример, демонстрирующий порядок вызова:
class MyClass:
def __new__(cls, *args, **kwargs):
print(f"1. Вызов __new__ для класса {cls.__name__}")
# Делегируем создание экземпляра родительскому классу object
instance = super().__new__(cls)
return instance
def __init__(self, value):
print(f"2. Вызов __init__ для экземпляра {id(self)}")
self.value = value
obj = MyClass(10)
print(f"3. Объект создан: {obj.value}")
Вывод:
1. Вызов __new__ для класса MyClass
2. Вызов __init__ для экземпляра 140701234567890
3. Объект создан: 10
Когда использовать __new__
?
Переопределение __new__
требуется редко. Основные случаи — реализация паттерна Singleton или создание неизменяемых (immutable) типов, наследуемых от str
, int
, tuple
.