Кто называет метакласс
Это на самом деле вытекает из обсуждения здесь на SO.
Укороченная версия
def meta(name, bases, class_dict)
return type(name, bases, class_dict)
class Klass(object):
__metaclass__ = meta
meta()
называется когдаKlass
объявление класса выполнено.
Какая часть кода (внутреннего Python) на самом деле вызываетmeta()
?
Длинная версия
Когда класс объявлен, некоторый код должен выполнить соответствующие проверки атрибутов и посмотреть, есть ли__metaclass__
заявлено по типу. Если такой существует, он должен выполнить вызов метода для этого метакласса с хорошо известным(class_name, bases, class_dict)
атрибутов. Мне не совсем понятно, какой код отвечает за этот вызов.
Я немного покопался в CPython (см. Ниже), но мне бы очень хотелось получить что-то ближе к определенному ответу.
Вариант 1: вызывается напрямую
Вызов метакласса встроен в синтаксический анализ класса. Если да, есть ли доказательства этому?
Вариант 2: вызываетсяtype.__new__()
Код вtype_call()
звонкиtype_new()
который в свою очередь вызывает_PyType_CalculateMetaclass()
, Это говорит о том, что разрешение метакласса фактически выполняется во время вызоваtype()
при попытке выяснить, какое значение вернутьtype()
Это было бы в соответствии с понятием, что «класс» является «вызываемый, который возвращает объект».
Вариант 3: что-то другое
Конечно, все мои догадки могут быть совершенно неверными.
Некоторые примеры случаев, которые мы придумали в чате:
Пример 1:
class Meta(type):
pass
class A:
__metaclass__ = Meta
A.__class__ == Meta
Это то, чтоMeta.__new__()
возвращается, так что это кажется законным. Метакласс ставит себя какA.__class__
Пример 2:
class Meta(type):
def __new__(cls, class_name, bases, class_dict):
return type(class_name, bases, class_dict)
class A(object):
__metaclass__ = Meta
A.__class__ == type
Редактировать 2: исправить исходную версию, правильно получитьMeta
отtype
.
Кажется, достаточно хорошо, но я не совсем уверен, что это делает то, что я думаю, что делает. Также: Каков канонический метод, чтобы заставить его вести себя как в Примере 1?
Изменить 3: Использованиеtype.__new__(...)
кажется, работает как ожидалось, что также кажется в пользу варианта 2.
Может ли кто-нибудь с более глубокими знаниями внутренней магии питона просветить меня?
Edit: A для довольно краткого учебника по метаклассам:http://blog.ionelmc.ro/2015/02/09/understanding-python-metaclasses/, Также есть некоторые действительно хорошие диаграммы, ссылки, а также подчеркивает различия между Python 2 и 3.
Редактировать 3: есть хороший ответ ниже для Python 3. Python 3 использует__build_class__
создать объект класса. Путь к коду --however-- отличается в Python 2.