__new__, вызывается при создании самого класса (не экземпляра). Чтобы повлиять на создание экземпляров, нужно переопределить метод __call__ в метаклассе. В этом методе можно добавить логику для модификации процесса создания объекта, например, внедрить общие атрибуты или выполнить предварительную инициализацию до вызова __init__.
Конструктор в метаклассе (обычно это метод __new__ или __init__) позволяет нам контролировать процесс создания классов, а не только объектов. Мы можем использовать его для динамического изменения атрибутов и методов класса, добавляя или модифицируя их во время создания класса.
Вот пример:
class Meta(type):
def __new__(mcs, name, bases, attrs):
# Добавляем атрибут, если его еще нет
if 'dynamically_added_attribute' not in attrs:
attrs['dynamically_added_attribute'] = 'Hello from Meta!'
# Модифицируем существующий атрибут (если он есть)
if 'existing_method' in attrs:
original_method = attrs['existing_method']
def modified_method(self, *args, **kwargs):
print("Вызов модифицированного метода")
return original_method(self, *args, **kwargs)
attrs['existing_method'] = modified_method
# Создаем класс с измененными атрибутами
return super().__new__(mcs, name, bases, attrs)
class MyClass(metaclass=Meta):
def __init__(self):
print("Инициализация MyClass")
def existing_method(self):
print("Это существующий метод")
# Использование
obj = MyClass()
print(obj.dynamically_added_attribute)
obj.existing_method()
Пояснения:
__new__ в метаклассе Meta перехватывает создание класса MyClass.__new__ мы можем добавлять, удалять или изменять атрибуты и методы класса, представленные в словаре attrs.dynamically_added_attribute, если он еще не существует.existing_method, оборачивая его в новую функцию, которая выводит сообщение перед вызовом оригинального метода.super().__new__(mcs, name, bases, attrs) вызывает родительский метод __new__ (из type) для фактического создания класса с измененными атрибутами. Важно его вызвать, чтобы не сломать создание класса.Когда это полезно:
Важно понимать, что метаклассы — мощный, но сложный инструмент. Их следует использовать, когда стандартных возможностей недостаточно, и только тогда, когда вы хорошо понимаете, как они работают. Неправильное использование метаклассов может привести к нечитаемому и трудно отлаживаемому коду.