Ответ
Методы __new__ и __init__ — это два ключевых этапа в жизненном цикле создания объекта в Python, но они выполняют принципиально разные задачи.
Ключевое различие: __new__ создает экземпляр, а __init__ его инициализирует (настраивает).
__new__(cls, ...)
- Роль: Создание (construction) объекта. Отвечает за выделение памяти под новый экземпляр.
- Вызывается: Первым, до
__init__. - Тип: Статический метод (хотя и не требует декоратора
@staticmethod), первым аргументом принимает классcls. - Возвращаемое значение: Должен вернуть новый экземпляр класса. Если он этого не сделает,
__init__не будет вызван.
__init__(self, ...)
- Роль: Инициализация (initialization) объекта. Заполняет атрибуты уже созданного экземпляра.
- Вызывается: Вторым, после
__new__. - Тип: Метод экземпляра, первым аргументом принимает созданный экземпляр
self. - Возвращаемое значение: Ничего не возвращает (
None).
Пример, демонстрирующий порядок вызова:
class MyClass:
def __new__(cls, *args, **kwargs):
print(f"1. Вызов __new__ для класса {cls.__name__}")
# Делегируем создание экземпляра родительскому классу object
instance = super().__new__(cls)
return instance
def __init__(self, value):
print(f"2. Вызов __init__ для экземпляра {id(self)}")
self.value = value
obj = MyClass(10)
print(f"3. Объект создан: {obj.value}")
Вывод:
1. Вызов __new__ для класса MyClass
2. Вызов __init__ для экземпляра 140701234567890
3. Объект создан: 10
Когда использовать __new__?
Переопределение __new__ требуется редко. Основные случаи — реализация паттерна Singleton или создание неизменяемых (immutable) типов, наследуемых от str, int, tuple.
Ответ 18+ 🔞
А, ну вот, смотри, объясняю как для дебила, но ты не обижайся, я сам когда-то нихуя не понимал. Есть в Питоне два таких метода, __new__ и __init__, которые постоянно путают, как близнецов-уродов. А разница-то, блядь, принципиальная, как между родить ребёнка и потом ему имя дать.
Вот представь, __new__ — это как сперматозоид с яйцеклеткой встречается, нихуя себе, зачатие, создание новой сущности, выделение памяти под неё, вся эта техническая магия. А __init__ — это ты уже родившемуся младенцу памперс надеваешь, имя записываешь и в кроватку кладёшь. Инициализация, ёпта! Без первого — второго просто не будет, потому что инициализировать-то нечего, пиздец.
__new__(cls, ...) — Создатель, Архитектор, Отец родной
- Чем занимается: Создаёт объект, внатуре. Выделяет память, колдует, материализует экземпляр из пустоты. Это статический метод, ему похуй на
self, он работает с классом (cls). - Когда вызывается: Самый первый, ещё до всех этих ваших инициализаций.
- Что должен сделать: Вернуть, блядь, новый экземпляр. Если он вернёт
Noneили какую-то хуйню —__init__даже не чихнёт в его сторону. Всё, накрылся медным тазом.
__init__(self, ...) — Отдел кадров, Дизайнер интерьеров, Нянька
- Чем занимается: Настраивает уже готовый объект. Вот тебе
self— держи, это твоё новое тело. Наполняй его атрибутами, настраивай, делай красиво. - Когда вызывается: Сразу после
__new__, если тот не обосрался. - Что должен сделать: Ничего не возвращает. Просто поработал с
selfи всё, доволен как слон.
Вот смотри, живой пример, чтоб вообще всё стало ясно, как божий день:
class MyClass:
def __new__(cls, *args, **kwargs):
print(f"1. Вызов __new__ для класса {cls.__name__}")
# Тут мы, сука, просим у родительского object: 'дай, блядь, памяти!'
instance = super().__new__(cls)
return instance
def __init__(self, value):
print(f"2. Вызов __init__ для экземпляра {id(self)}")
self.value = value
obj = MyClass(10)
print(f"3. Объект создан: {obj.value}")
Что на экране будет:
1. Вызов __new__ для класса MyClass
2. Вызов __init__ для экземпляра 140701234567890
3. Объект создан: 10
Видишь порядок? Сначала __new__ материализовал объект, потом __init__ его причесал и дал ему value = 10.
А зачем вообще __new__ трогать, если он такой скрытный?
Обычно — да, него не трогают, он сам справляется. Но есть моменты, когда без него — никуда. Например, если ты хочешь сделать Singleton (чтоб класс был один, как ядрёна вошь), или если ты наследуешься от встроенных неизменяемых типов вроде str или tuple — там без переопределения __new__ нихуя не получится, потому что создание таких объектов — это особая, ебаная магия.
Короче, запомни: __new__ — рожает, __init__ — воспитывает. И не путай их, а то получится, как в той поговорке: начал за здравие, а кончил за ебись-колотись.