Создание объекта в Python — это всегда двухшаговый процесс:
__new__ — «стройка»: создаётся сам объект (экземпляр), выделяется память.
__init__ — «обустройство»: в созданный объект записываются атрибуты и стартовые значения.
Удобная аналогия: __new__ строит пустой дом, __init__ расставляет в нём мебель.
__new__
Метод __new__ создаёт экземпляр и вызывается до __init__. Первым аргументом он получает ссылку на класс cls и должен вернуть новый объект. В обычных классах ты его почти никогда не переопределяешь.
__init__
Метод __init__ инициализирует экземпляр: вызывается после __new__, первым аргументом получает self — уже созданный объект, и обычно просто заполняет его атрибуты. Всегда возвращает None.
В 99% случаев ты работаешь именно с __init__:
class User:
def __init__(self, name: str, email: str):
self.name = name
self.email = email
user = User("Alex", "alex@example.com")
Здесь __new__ молча вызывается под капотом через object.__new__, ты его не видишь и не трогаешь.
Когда реально нужен __new__
Переопределять __new__ нужно в нескольких специфических случаях:
1. Наследование от неизменяемых типов (int, str, tuple)
Значение таких объектов задаётся при создании, а не при инициализации, поэтому управлять им можно только в __new__:
class EvenInt(int):
def __new__(cls, value):
if value % 2 != 0:
raise ValueError("Only even numbers allowed")
return super().__new__(cls, value)
EvenInt(4) # OK
EvenInt(3) # ValueError
2. Синглтон (один объект на класс)
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
3. Метаклассы и продвинутые паттерны
Когда тебе нужно контролировать сам процесс инстанцирования на уровне метакласса.
Как сформулировать на собеседовании
__new__ создаёт объект и возвращает его, __init__ получает уже созданный объект и заполняет его атрибутами. Сначала вызывается __new__, затем __init__. В обычных классах ты переопределяешь только __init__, а __new__ нужен в редких случаях: при наследовании от неизменяемых типов (int, str и т.п.) и при реализации паттернов вроде синглтона.