Hello I am recently looking about the metaclass
in Python.
I learned about we can attach a metaclass to a class in this way:
class Metaclass(type):
...
class MyClass(metaclass=Metaclass):
...
I wonder what's the principle of the keyword argument (metaclass=...
) in the above example. There seems no description for that in the doc
I know that there is keyword argument for a function, but I've never seen the form occurred in class inheritance.
We know that we can create a class using type()
function in this way
cls = type(class_name, (base_class,), {func_name: func_ref})
Considering the metaclass=...
form, how can I pass metaclass when creating class using type()
instead of class
keyword?
Thanks stackoverflowers!
In general, the keyword arguments used with a class
statement are passed to __init_subclass__
, to be used however that function sees fit. metaclass
, however, is used by the code generator itself to determine what gets called in order to define the class.
The metaclass is not an argument to be passed to a call to type
; it is the callable that gets called instead of type
. Very roughly speaking,
class MyClass(metaclass=Metaclass):
...
is turned into
MyClass = Metaclass('MyClass', (), ...)
type
is simply the default metaclass.
(The gory details of how a class
statement is executed can be found in Section 3.3.3 of the language documentation.)
Note that a metaclass does not have to be a subclass of type
. You can do truly horrific things with metaclasses, like
>>> class A(metaclass=lambda x, y, z: 3): pass
...
>>> type(A)
<class 'int'>
>>> A
3
It doesn't really matter what the metaclass returns, as long as it accepts 3 arguments.
Please don't write actual code like this, though. A class
statement should produce something that at least resembles a type.
In some sense, class
statements are less magical than other statements. def
statements, for example, can't be customized to produce something other than instances of function
, and it's far harder to create a function
object by calling types.FunctionType
explicitly.