Какие специальные методы Python вызываются при создании экземпляра класса?

Ответ

При создании экземпляра класса в Python вызываются два специальных метода в строгом порядке:

  1. __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
  2. __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__ для исходного класса не будет вызван.