Я пытаюсь узнать, как работают метаклассы в Python 3. Вещи, которые я хочу знать: какие функции вызываются, в каком порядке, а также их сигнатуры и возвращаемые значения.
В качестве примера я знаю__prepare__
вызывается, когда создается экземпляр класса с метаклассом с аргументами metaclass, name_of_subclass, bases
и возвращает словарь, представляющий будущее пространство имен экземпляра объекта.
Мне кажется, я хорошо понимаю шаг __prepare__
в процессе.Чего я не делаю, так это __init__
, __new__
и __call__
.Каковы их аргументы?Что они возвращают?Как они все называют друг друга, или вообще как идет процесс?В настоящее время я застрял в понимании, когда вызывается __init__
.
Вот код, с которым я возился, чтобы ответить на мои вопросы:
#!/usr/bin/env python3
class Logged(type):
@classmethod
def __prepare__(cls, name, bases):
print('In meta __prepare__')
return {}
def __call__(subclass):
print('In meta __call__')
print('Creating {}.'.format(subclass))
return subclass.__new__(subclass)
def __new__(subclass, name, superclasses, attributes, **keyword_arguments):
print('In meta __new__')
return type.__new__(subclass, name, superclasses, attributes)
def __init__(subclass, name, superclasses, attributes, **keyword_arguments):
print('In meta __init__')
class Thing(metaclass = Logged):
def __new__(this, *arguments, **keyword_arguments):
print('In sub __new__')
return super(Thing, this).__new__(this)
def __init__(self, *arguments, **keyword_arguments):
print('In sub __init__')
def hello(self):
print('hello')
def main():
thing = Thing()
thing.hello()
if __name__ == '__main__':
main()
Из этого и некоторыхgoogling, я знаю, что __new__
на самом деле является статическим методом, который возвращает экземпляр некоторого объекта (обычно это объект, в котором определен __new__
, но не всегда), и что __init__
вызывается из экземпляра, когда он сделан,По этой логике меня смущает, почему Thing.__init__()
не вызывается.Может ли кто-нибудь осветить?
Вывод этого кода выводит «привет», поэтому создается экземпляр Thing, что еще больше сбивает меня с толку насчет init.Вот вывод:
In meta __prepare__
In meta __new__
In meta __init__
In meta __call__
Creating <class '__main__.Thing'>
In sub __new__
hello
Любая помощь в понимании метаклассов будет принята с благодарностью.Я прочитал довольно много уроков, но пропустил некоторые из этих деталей.