Что такое new. И чем он отличается от init. В какой последовательности они выполняютсяpython-98

В Python создание объекта происходит в два этапа, за которые отвечают два разных магических метода: __new__ и __init__. Рассмотрим их различия и последовательность выполнения.

1. Метод __new__

Основные характеристики:

  • Создает новый экземпляр класса (конструктор)
  • Вызывается первым при создании объекта
  • Должен вернуть новый объект (обычно экземпляр класса)
  • Принимает класс первым аргументом (cls)
  • Может возвращать объект другого типа

Пример:

class Example:
    def __new__(cls, *args, **kwargs):
        print("__new__ выполняется")
        instance = super().__new__(cls)  # Создаем экземпляр
        return instance

2. Метод __init__

Основные характеристики:

  • Инициализирует созданный экземпляр
  • Вызывается после __new__
  • Не возвращает значение (None)
  • Принимает self (уже созданный экземпляр)
  • Отвечает за начальное состояние объекта

Пример:

    def __init__(self, value):
        print("__init__ выполняется")
        self.value = value

Последовательность выполнения

При вызове Example() происходит:

  1. Сначала вызывается __new__:
    • Получает класс (cls)
    • Создает и возвращает новый экземпляр
  2. Затем вызывается __init__:
    • Получает созданный экземпляр (self)
    • Инициализирует атрибуты

Пример полного цикла:

obj = Example(10)
# Вывод:
# __new__ выполняется
# __init__ выполняется

Ключевые различия

Характеристика __new__ __init__
Назначение Создание объекта Инициализация объекта
Аргумент cls (класс) self (экземпляр)
Возвращаемое значение Новый экземпляр None
Вызов Первым Вторым
Использование Реже, для особых случаев Часто, в большинстве классов

Практическое применение __new__

  1. Создание неизменяемых объектов:
class Immutable:
    def __new__(cls, value):
        instance = super().__new__(cls)
        instance._value = value
        return instance

    def __setattr__(self, name, value):
        raise AttributeError("Неизменяемый объект")
  1. Шаблон Одиночка (Singleton):
class Singleton:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance
  1. Возврат объектов другого типа:
class PositiveNumber:
    def __new__(cls, value):
        if value > 0:
            return super().__new__(cls)
        return None

Когда что использовать

  • Обычные случаи: только __init__ (99% кода)
  • Особые случаи:
    • Контроль над созданием экземпляра
    • Неизменяемые объекты
    • Паттерны проектирования (Singleton, Factory)
    • Наследование от встроенных неизменяемых типов

Пример наследования от tuple

class CustomTuple(tuple):
    def __new__(cls, a, b):
        return super().__new__(cls, (a, b))

    def __init__(self, a, b):
        self.a = a  # Не сработает для tuple!
        # Для неизменяемых типов вся работа в __new__

Резюмируем

  1. __new__ - конструктор, создает объект (вызывается первым)
  2. __init__ - инициализатор, настраивает объект (вызывается вторым)
  3. Последовательность: __new__ → (создание объекта) → __init__
  4. В большинстве случаев достаточно __init__
  5. __new__ нужен для:
    • Контроля процесса создания
    • Неизменяемых объектов
    • Специальных паттернов проектирования
  6. Для изменяемых объектов обычно работают в __init__, для неизменяемых - в __new__

Понимание различий между этими методами важно для продвинутой работы с классами в Python и реализации специфического поведения при создании объектов.