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

Чем отличается __new__ от __init__?

2.2 Middle🔥 81 комментариев
#Python Core

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

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

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

Отличие new от init

new и init — это два разных волшебных метода, которые работают на разных этапах создания объекта в Python.

new — создание объекта

new отвечает за создание самого экземпляра класса. Это статический метод, который вызывается раньше всех и принимает класс в качестве первого аргумента:

class MyClass:
    def __new__(cls, value):
        print(f"__new__ вызван для класса {cls.__name__}")
        instance = super().__new__(cls)  # Создаём пустой объект
        return instance  # Возвращаем новый объект

obj = MyClass(42)
# Вывод: __new__ вызван для класса MyClass

init — инициализация объекта

init отвечает за инициализацию уже созданного объекта. Это обычный метод, который получает готовый объект (self) и его аргументы:

class MyClass:
    def __init__(self, value):
        print(f"__init__ вызван, получен объект {id(self)}")
        self.value = value  # Инициализируем атрибуты

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

Порядок вызова

При создании объекта сначала вызывается new, затем init:

class Point:
    def __new__(cls, x, y):
        print("1. __new__ создаёт объект")
        return super().__new__(cls)
    
    def __init__(self, x, y):
        print("2. __init__ инициализирует объект")
        self.x = x
        self.y = y

point = Point(10, 20)
# Вывод:
# 1. __new__ создаёт объект
# 2. __init__ инициализирует объект

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

1. Синглтон через new:

class Singleton:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance
    
    def __init__(self):
        self.value = 42

s1 = Singleton()
s2 = Singleton()
print(s1 is s2)  # True — один и тот же объект

2. Кэширование объектов:

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

obj1 = CachedClass("a")
obj2 = CachedClass("a")
print(obj1 is obj2)  # True

3. Контроль типов (например, для чисел):

class Number:
    def __new__(cls, value):
        if isinstance(value, int):
            return super().__new__(cls)
        else:
            raise TypeError(f"Expected int, got {type(value).__name__}")
    
    def __init__(self, value):
        self.value = value

n = Number(5)  # ОК
# Number("5")  # TypeError

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

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

Отличие очень важно понимать для работы с наследованием и специальными паттернами проектирования в Python.

Чем отличается __new__ от __init__? | PrepBro