Ответ
Метод __new__
в Python отвечает за создание экземпляра класса, в то время как __init__
отвечает за его инициализацию. __new__
вызывается перед __init__
и должен вернуть новый экземпляр класса.
Это низкоуровневый метод, который используется редко, но необходим в следующих случаях:
- Реализация паттерна Singleton: Гарантирует, что у класса будет только один экземпляр.
- Наследование от неизменяемых (immutable) типов: При наследовании от таких типов, как
str
,int
илиtuple
, необходимо переопределить__new__
, так как изменить их после создания уже нельзя. - Создание объектов-заместителей: Когда нужно вернуть экземпляр другого класса в зависимости от переданных аргументов (реализация фабричного метода).
Пример реализации Singleton:
class DatabaseConnection:
_instance = None
def __new__(cls, *args, **kwargs):
# Если экземпляр еще не создан
if not cls._instance:
# Создаем новый экземпляр, вызывая __new__ родительского класса
cls._instance = super().__new__(cls)
# Возвращаем существующий или только что созданный экземпляр
return cls._instance
def __init__(self, dsn):
# Этот метод будет вызываться каждый раз,
# но на одном и том же экземпляре.
self.dsn = dsn
# Оба вызова вернут один и тот же объект
db1 = DatabaseConnection("user:pass@host1")
db2 = DatabaseConnection("user:pass@host2")
print(id(db1) == id(db2)) # Вывод: True
print(db1.dsn) # Вывод: user:pass@host2
Ключевое отличие от __init__
:
__new__(cls, ...)
: Первый аргумент — классcls
. Создает и возвращает экземпляр. Является статическим методом.__init__(self, ...)
: Первый аргумент — экземплярself
. Ничего не возвращает. Инициализирует уже созданный экземпляр.