Кто называет метакласс

Это на самом деле вытекает из обсуждения здесь на 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.

Ответы на вопрос(3)

Ваш ответ на вопрос