__init__: Это самый распространенный способ. Можно добавить свою логику инициализации экземпляра класса.__new__: Метод __new__ отвечает за создание экземпляра класса, а __init__ - за его инициализацию. Можно переопределить __new__ для контроля над процессом создания объекта.Чтобы изменить поведение конструктора класса в Python, можно использовать несколько подходов:
__init__: Это самый распространенный способ.  Вы определяете метод __init__ в вашем классе и добавляете или изменяете логику, необходимую для инициализации экземпляра класса. Важно помнить о вызове super().__init__(...) (если класс наследуется от другого класса), чтобы инициализировать атрибуты родительского класса, если это необходимо.  Если вы не вызываете super().__init__(...),  то вы полностью заменяете инициализацию родительского класса.
            
class MyClass:
    def __init__(self, arg1, arg2="default"):
        self.attribute1 = arg1
        self.attribute2 = arg2
        print("Конструктор MyClass вызван")
class MySubClass(MyClass):
    def __init__(self, arg1, arg3):
        super().__init__(arg1)  # Вызов конструктора родительского класса
        self.attribute3 = arg3
        print("Конструктор MySubClass вызван")
__new__: Метод __new__ отвечает за создание экземпляра класса, а __init__ - за его инициализацию.  __new__ получает класс (cls) как первый аргумент и должен возвращать экземпляр этого класса.  Если вы хотите контролировать процесс создания объекта (например, реализовать Singleton), __new__ – подходящий вариант. __init__ вызывается *после* __new__ только в том случае, если __new__ возвращает экземпляр класса (или его подкласса).  Если __new__ возвращает что-то другое, __init__ не вызывается.
            
class Singleton:
    _instance = None
    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            print("Создан новый экземпляр")
        else:
            print("Возвращен существующий экземпляр")
        return cls._instance
    def __init__(self, value):
        # Инициализация экземпляра, если он создан впервые
        if not hasattr(self, 'value'):  # Проверка, инициализирован ли экземпляр ранее
            self.value = value
class MyMeta(type):
    def __call__(cls, *args, **kwargs):
        print("Перед созданием экземпляра")
        instance = super().__call__(*args, **kwargs)
        print("После создания экземпляра")
        return instance
class MyClass(metaclass=MyMeta):
    def __init__(self, value):
        self.value = value
        print("Инициализация MyClass")
def add_greeting(cls):
    class Wrapper:
        def __init__(self, *args, **kwargs):
            self.instance = cls(*args, **kwargs)
            self.instance.greeting = "Hello!"
        def __getattr__(self, name):
            return getattr(self.instance, name)
    return Wrapper
@add_greeting
class Greeter:
    def __init__(self, name):
        self.name = name
greeter = Greeter("Alice")
print(greeter.name)  # Выведет: Alice
print(greeter.greeting) # Выведет: Hello!
Выбор конкретного подхода зависит от требуемой степени контроля над процессом создания и инициализации объектов, а также от сложности решаемой задачи.