Ответ
При создании экземпляра класса в Python вызываются два специальных метода в строгом порядке:
-
__new__(cls, *args, **kwargs):- Назначение: Это статический метод, который отвечает за создание и возвращение нового, пустого экземпляра класса. Он вызывается до
__init__. - Почему: Позволяет контролировать процесс создания объекта, например, возвращать экземпляр другого класса (для паттерна Singleton) или использовать кэширование. Обычно вызывает
super().__new__(cls, ...), чтобы делегировать фактическое создание объекта базовому классу. - Пример (Singleton):
class Singleton: _instance = None def __new__(cls, *args, **kwargs): if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance
- Назначение: Это статический метод, который отвечает за создание и возвращение нового, пустого экземпляра класса. Он вызывается до
-
__init__(self, *args, **kwargs):- Назначение: Это метод-инициализатор, который отвечает за инициализацию (настройку) уже созданного экземпляра. Он получает созданный
__new__объект (self) и заполняет его атрибутами. - Почему: Используется для установки начальных значений атрибутов объекта, выполнения необходимых настроек после его создания, но до того, как объект будет полностью готов к использованию.
- Пример:
class MyClass: def __init__(self, value): self.value = value # Инициализация атрибута
- Назначение: Это метод-инициализатор, который отвечает за инициализацию (настройку) уже созданного экземпляра. Он получает созданный
Порядок вызова и взаимодействие:
Когда вы пишете MyClass(...), сначала вызывается MyClass.__new__(), который создает объект. Затем, если __new__ вернул экземпляр MyClass (или его подкласса), вызывается MyClass.__init__() для инициализации этого объекта.
Пример демонстрации порядка:
class Example:
def __new__(cls, *args, **kwargs):
print("1. __new__ called: Создание экземпляра")
instance = super().__new__(cls)
return instance
def __init__(self, value):
print(f"2. __init__ called: Инициализация экземпляра со значением {value}")
self.value = value
obj = Example(42)
# Вывод:
# 1. __new__ called: Создание экземпляра
# 2. __init__ called: Инициализация экземпляра со значением 42
Важное примечание: Если метод __new__ возвращает экземпляр класса, отличного от того, для которого он был вызван, то метод __init__ для исходного класса не будет вызван.