This actually stems from a discussion here on SO.
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
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() 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
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:
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
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
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.