Ответ
При создании экземпляра класса в Python сначала вызывается статический метод __new__, а затем — метод экземпляра __init__.
-
__new__(cls, ...)- Отвечает за создание и возврат экземпляра класса. Это первый шаг в жизненном цикле объекта.
- Является статическим методом (первый аргумент — сам класс
cls). - Должен вернуть экземпляр класса (или его подкласса), иначе
__init__не будет вызван. - Используется редко, в основном для реализации паттернов (например, Singleton) или для кастомизации создания неизменяемых (immutable) типов.
-
__init__(self, ...)- Отвечает за инициализацию уже созданного экземпляра. Его задача — установить начальные атрибуты объекта.
- Является обычным методом экземпляра (первый аргумент —
self, ссылка на созданный экземпляр). - Ничего не возвращает (точнее, неявно возвращает
None).
Пример последовательности вызовов:
class MyClass:
def __new__(cls, *args, **kwargs):
print(f"1. Вызов __new__ для класса {cls.__name__}")
# Создаем экземпляр с помощью __new__ родительского класса
instance = super().__new__(cls)
print(" Экземпляр создан")
return instance
def __init__(self, value):
print(f"2. Вызов __init__ для экземпляра {id(self)}")
self.value = value
print(" Экземпляр инициализирован")
# При создании объекта вызываются оба метода
obj = MyClass(42)
print(f"nСоздан объект: {obj.value}")
Вывод:
1. Вызов __new__ для класса MyClass
Экземпляр создан
2. Вызов __init__ для экземпляра 140343833620240
Экземпляр инициализирован
Создан объект: 42 Ответ 18+ 🔞
А, слушай, вот тебе классика, блядь, про то, как в Питоне объекты на свет появляются. Это ж целая драма в двух актах, ёпта! Сначала, сука, __new__ выходит на сцену, как режиссёр-постановщик, а потом уже __init__ прибегает, как гримёр-костюмер, и начинает этот свежеиспечённый экземпляр разукрашивать.
Так, по порядку, блядь, чтобы не пиздец в мозгах был.
Первый акт, __new__(cls, ...)
Этот чувак — статик, ему похуй на конкретные экземпляры пока что. Его задача — взять чертежи класса (cls) и, блядь, создать и вернуть сам объект. Вообще, физически в памяти его слепить. Если он, мудак, ничего не вернёт или вернёт какую-то левую хуйню (не экземпляр этого класса), то второй акт отменяется. __init__ просто не позовут, и всё. Используют его редко, в каких-то извращённых случаях, типа Синглтона, чтобы все на один и тот же объект ссылались, или для immutable типов, где после создания уже нихуя не поменяешь.
Второй акт, __init__(self, ...)
А вот этот товарищ уже работает с готовым продуктом. Ему приносят свеженький, только что созданный экземпляр (это и есть self) и говорят: «На, инициализируй, сука!». Он туда атрибуты навешивает, значения устанавливает — короче, обживает. Он нихуя не возвращает, его работа — навести марафет внутри.
Пример, чтобы совсем пиздец понятно стало:
class MyClass:
def __new__(cls, *args, **kwargs):
print(f"1. Вызов __new__ для класса {cls.__name__}")
# Создаем экземпляр с помощью __new__ родительского класса
instance = super().__new__(cls)
print(" Экземпляр создан")
return instance
def __init__(self, value):
print(f"2. Вызов __init__ для экземпляра {id(self)}")
self.value = value
print(" Экземпляр инициализирован")
# При создании объекта вызываются оба метода
obj = MyClass(42)
print(f"nСоздан объект: {obj.value}")
Что на экране будет, блядь:
1. Вызов __new__ для класса MyClass
Экземпляр создан
2. Вызов __init__ для экземпляра 140343833620240
Экземпляр инициализирован
Создан объект: 42
Видишь? Сначала __new__ материализовал эту сущность из ничего, присвоил ей адрес в памяти (этот id). А потом __init__ пришёл, увидел этот адрес и засунул туда значение 42. Вот и вся магия, блядь. __new__ — это про «быть», а __init__ — про «каким быть».