← Назад к вопросам

В чем разница между __new__ и __init__?

2.3 Middle🔥 111 комментариев
#Python

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI28 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между new и init

Это два ключевых метода в жизненном цикле создания объекта в Python. Они работают на разных уровнях.

new (Создание объекта)

Предназначение: создает новый экземпляр класса

  • Вызывается первым
  • Статический метод (принимает cls, не self)
  • Отвечает за выделение памяти под объект
  • Должен вернуть новый экземпляр класса
  • Если new не вернул экземпляр класса, init не будет вызван
class MyClass:
    def __new__(cls, *args, **kwargs):
        print("__new__ вызван - создание объекта")
        instance = super().__new__(cls)  # Создаём объект
        return instance  # Возвращаем новый объект
    
    def __init__(self, value):
        print("__init__ вызван - инициализация")
        self.value = value

obj = MyClass(42)
# __new__ вызван - создание объекта
# __init__ вызван - инициализация

init (Инициализация объекта)

Предназначение: инициализирует атрибуты созданного объекта

  • Вызывается вторым
  • Обычный метод (принимает self)
  • Отвечает за установку начальных значений атрибутов
  • Возвращает None
  • Работает с уже созданным объектом
class User:
    def __init__(self, name, age):
        print("__init__ вызван")
        self.name = name
        self.age = age

user = User("Иван", 30)
# Объект уже существует, __init__ просто заполняет атрибуты
print(user.name)  # Иван

Последовательность вызовов

MyClass(args, kwargs)
    |
    v
__new__(cls, args, kwargs)  <- Создание объекта
    |
    v
(возвращает instance)
    |
    v
__init__(instance, args, kwargs)  <- Инициализация объекта
    |
    v
instance готов к использованию

Практический пример

class Singleton:
    _instance = None
    
    def __new__(cls):
        # Контролируем создание - возвращаем один экземпляр
        if cls._instance is None:
            print("Создаю новый экземпляр Singleton")
            cls._instance = super().__new__(cls)
        else:
            print("Возвращаю существующий экземпляр")
        return cls._instance
    
    def __init__(self):
        print("__init__ вызван")
        self.created_at = None

# Первый вызов
s1 = Singleton()
# Создаю новый экземпляр Singleton
# __init__ вызван

# Второй вызов
s2 = Singleton()
# Возвращаю существующий экземпляр
# __init__ вызван

print(s1 is s2)  # True - это один и тот же объект

Когда нужен new?

1. Singleton паттерн - контроль количества экземпляров

class Database:
    _instance = None
    
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super().__new__(cls)
        return cls._instance

2. Иммутабельные объекты - кэширование и переиспользование

class ImmutablePoint:
    _cache = {}
    
    def __new__(cls, x, y):
        key = (x, y)
        if key not in cls._cache:
            instance = super().__new__(cls)
            cls._cache[key] = instance
        return cls._cache[key]
    
    def __init__(self, x, y):
        self.x = x
        self.y = y

p1 = ImmutablePoint(1, 2)
p2 = ImmutablePoint(1, 2)
print(p1 is p2)  # True - тот же объект из кэша

3. Работа с встроенными типами - создание подклассов

class MyList(list):
    def __new__(cls, iterable):
        # list не вызывается __init__ как обычный класс
        # используем __new__ для инициализации
        return super().__new__(cls, iterable)

ml = MyList([1, 2, 3])
print(ml)  # [1, 2, 3]

Важные моменты

Аспектnewinit
ВызовПервыйВторой
Тип метода@staticmethodОбычный
Первый параметрclsself
ВозвращаетЭкземпляр классаNone
НазначениеСоздание памятиИнициализация
ОбязателенНет (есть по умолчанию)Нет (есть по умолчанию)

Типичная ошибка

# Неправильно - забыли вернуть instance
class Wrong:
    def __new__(cls):
        super().__new__(cls)  # Не вернули!
    
    def __init__(self):
        self.value = 42

obj = Wrong()  # Возвращает None!
print(obj.value)  # AttributeError!

# Правильно
class Right:
    def __new__(cls):
        return super().__new__(cls)  # Вернули instance
    
    def __init__(self):
        self.value = 42

obj = Right()
print(obj.value)  # 42

Вывод: используй new только когда нужно контролировать создание объекта (singleton, кэширование). В 99% случаев достаточно init.

В чем разница между __new__ и __init__? | PrepBro