Ответ
Методы __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.