Какова роль метода __new__ в Python и чем он отличается от __init__?

Ответ

Метод __new__ — это статический метод класса, который отвечает за создание и возврат нового экземпляра класса. Он вызывается перед методом __init__.

В свою очередь, __init__ — это метод экземпляра, который отвечает за инициализацию уже созданного объекта (например, за установку его атрибутов). Он ничего не возвращает.

Ключевые отличия:

Характеристика __new__(cls, ...) __init__(self, ...)
Назначение Создание экземпляра Инициализация экземпляра
Тип метода Статический (первый аргумент — класс cls) Экземпляра (первый аргумент — экземпляр self)
Возвращаемое значение Должен вернуть экземпляр класса Не должен ничего возвращать (None)
Порядок вызова Вызывается первым Вызывается вторым, после __new__

Основные случаи использования __new__:

  1. Реализация паттерна Singleton, когда нужно контролировать процесс создания и гарантировать наличие только одного экземпляра класса.
  2. Наследование от неизменяемых (immutable) типов, таких как str, int или tuple, поскольку их значения нужно задать на этапе создания.

Пример (Singleton):

class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        # Если экземпляр еще не создан
        if cls._instance is None:
            # Создаем новый экземпляр, вызывая __new__ родительского класса
            cls._instance = super().__new__(cls)
        # Возвращаем существующий или только что созданный экземпляр
        return cls._instance

# Проверка
a = Singleton()
b = Singleton()

print(f"a is b: {a is b}")  # Вывод: a is b: True