Who calls the metaclass

僤鯓⒐⒋嵵緔 提交于 2019-12-03 12:33:08

You can find the answer relatively easily. First, lets find the opcode for building a class.

>>> def f():
    class A(object):
        __metaclass__ = type

>>> import dis
>>> dis.dis(f)
  2           0 LOAD_CONST               1 ('A')
              3 LOAD_GLOBAL              0 (object)
              6 BUILD_TUPLE              1
              9 LOAD_CONST               2 (<code object A at 0000000001EBDA30, file "<pyshell#3>", line 2>)
             12 MAKE_FUNCTION            0
             15 CALL_FUNCTION            0
             18 BUILD_CLASS         
             19 STORE_FAST               0 (A)
             22 LOAD_CONST               0 (None)
             25 RETURN_VALUE    

So the opcode is BUILD_CLASS. Now let's search the source for that term (easily done on the github mirror).

You get a couple of results, but the most interesting of which is Python/ceval.c which declares the function static PyObject * build_class(PyObject *, PyObject *, PyObject *); and has a case statement for BUILD_CLASS. Search through the file and you can find the function definition of build_class starting at line 4430. And on line 4456 we find the bit of code you are looking for:

result = PyObject_CallFunctionObjArgs(metaclass, name, bases, methods,
                      NULL);

So the answer is the metaclass is resolved and called by the function that is responsible for executing the BUILD_CLASS opcode.

In Python 3, the metaclass is called in the code for the __build_class__ builtin function (which is called to handle class statements). This function is new in Python 3, and the equivalent C function build_class in Python 2 is not publicly exposed at the Python level. You can however find the source in python/ceval.c

Anyway, here's the relevant call to the metaclass object in the Python 3 __build_class__ implementation:

cls = PyEval_CallObjectWithKeywords(meta, margs, mkw);

The variable meta is the metaclass (either type or another metaclass found from an argument or from the type of a base class). margs is a tuple with the positional arguments (name, bases, dct) and mkw is a dictionary with the keyword arguments to the metaclass (a Python 3 only thing).

The Python 2 code does something similar:

result = PyObject_CallFunctionObjArgs(metaclass, name, bases, methods,
                                      NULL);

Meta classes are "instantiated" by interpreter when class definition is executed.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!