This actually stems from a discussion here on SO.
Short version
def meta(name, bases, class_dict)
return type(name, bases, class_dict)
class Klass(object):
__metaclass__ = meta
meta()
is called when Klass
class declaration is executed.
Which part of the (python internal) code actually calls meta()
?
Long version
When the class is declared, some code has to do the appropriate attribute checks and see if there is a __metaclass__
declared on a type. If such exists, it has to perform a method call on that metaclass with the well known (class_name, bases, class_dict)
attributes. It is not really clear to me which code is responsible for that call.
I have done some digging in CPython (see below), but I would really like to have something closer to a definite answer.
Option 1: Called directly
The metaclass call is hardwired into the class parsing. If so, is there any evidence for this?
Option 2: It is called by type.__new__()
Code in type_call()
calls type_new()
which in turn calls _PyType_CalculateMetaclass()
. This suggests that metaclass resolution is actually done during the call to type()
when trying to find out which value to return from type()
This would be in in line with the notion that a "class" is a "callable that returns an object".
Option 3: Something different
All my guesses maybe completely wrong, of course.
Some example cases that we came up with in chat:
Example 1:
class Meta(type):
pass
class A:
__metaclass__ = Meta
A.__class__ == Meta
This is what Meta.__new__()
returns, so this seems legit. The metaclass puts itself as A.__class__
Example 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
Edit 2: correct initial version, properly derive Meta
from type
.
Seems okay enough, but I'm not really sure this does what I think it does. Also: What is the canonical method to make it behave like in Example 1?
Edit 3: Using type.__new__(...)
seems to work as expected, which also seems in favor of Option 2.
Can anybody with more in-depth knowledge of internal python magic enlighten me?
Edit: A for a quite concise primer on metaclasses: http://blog.ionelmc.ro/2015/02/09/understanding-python-metaclasses/. Also has some really nice diagrams, references and also highlights the differences between python 2 and 3.
Edit 3: There is a good answer below for Python 3. Python 3 uses __build_class__
to create a class object. The code path is --however-- different in Python 2.
You can find the answer relatively easily. First, lets find the opcode for building a class.
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 functionstatic PyObject * build_class(PyObject *, PyObject *, PyObject *);
and has a case statement forBUILD_CLASS
. Search through the file and you can find the function definition ofbuild_class
starting at line 4430. And on line 4456 we find the bit of code you are looking for: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 handleclass
statements). This function is new in Python 3, and the equivalent C functionbuild_class
in Python 2 is not publicly exposed at the Python level. You can however find the source inpython/ceval.c
Anyway, here's the relevant call to the metaclass object in the Python 3
__build_class__
implementation:The variable
meta
is the metaclass (eithertype
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)
andmkw
is a dictionary with the keyword arguments to the metaclass (a Python 3 only thing).The Python 2 code does something similar:
Meta classes are "instantiated" by interpreter when class definition is executed.