Вы, кажется, запутались между __new__
и метаклассами.__new__
вызывается для создания нового объекта (экземпляр из класса, класс из метакласса), это не крюк «класс создан».
Обычный шаблон:
Foo(...)
переведено на type(Foo).__call__(Foo, ...)
, см. поиск специальных методов , почему это так.type()
класса - это его метакласс. Стандартная реализация type.__call__
, используемая, когда Foo
- это пользовательский класс Python, вызовет __new__
для создания нового экземпляра, а затем вызовет__init__
метод в этом экземпляре, если результат действительно является экземпляром класса Foo
:
def __call__(cls, *args, **kwargs): # Foo(...) -> cls=Foo
instance = cls.__new__(cls, *args, **kwargs) # so Foo.__new__(Foo, ...)
if isinstance(instance, cls):
instance.__init__(*args, **kwargs) # Foo.__init__(instance, ...)
return instance
Так что Foo.__new__
не вызывается при создании самого класса Foo
, только когда экземпляров из Foo
созданы.
Обычно вам не нужно использовать __new__
в классах, потому что __init__
достаточно для инициализации атрибутов экземпляров,Но для неизменяемых типов, таких как int
или tuple
, вы можете использовать __new__
только для подготовки нового состояния экземпляра, так как вы не можете изменять атрибуты неизменяемого объекта после его создания.,__new__
также полезен, когда вы хотите изменить тип экземпляров ClassObj()
(например, вместо создания синглетонов или создания специализированных подклассов).
То же __call__
-> __new__
и, возможно, __init__
процесс применяется к метаклассам.Оператор class Foo: ...
реализуется путем вызова метакласса для создания объекта класса, передавая 3 аргумента: имя класса, базы классов и тело класса, как обычно словарь.С class Spam(metaclass = debugmeta): ...
это означает, что вызывается debugmeta('Spam', (), {...})
, что означает, что вызывается debugmeta.__new__(debugmeta, 'Spam', (), {...})
.
Ваша первая попытка a , настройка Spam.__new__
не работает, потому что вы нет создания объекта класса там.Вместо этого super().__new__(cls)
создает пустой Spam()
экземпляр без атрибутов, поэтому vars()
возвращает пустой словарь, а debugmethods()
в итоге ничего не делает.
Если вы хотите подключитьв создание класса, то вы хотите метакласс.