A point of python metaclass
Contents
Create class
dynamically
Python doc says:
By default, classes are constructed using
type()
. The class body is executed in a new namespace and the class name is bound locally to the result oftype(name, bases, namespace)
.
That’s means, a class
statement is equivalent to the call of type
method with three arguments:
- name: name of the class
- bases: tuple of the parent class (for inheritance, can be empty)
- attrs: dictionary containing attributes names and values.
For example, the following classes are identical:
|
|
as verified by the picture below:
The type
function is special:
With one argument, return the type of an object. The return value is a type object and generally the same object as returned by
object.__class__
.With three arguments, return a new type object. This is essentially a dynamic form of the
class
statement. The name string is the class name and becomes the__name__
attribute. The bases tuple contains the base classes and becomes the__bases__
attribute; if empty,object
, the ultimate base of all classes, is added. The dict dictionary contains attribute and method definitions for the class body; it may be copied or wrapped before becoming the__dict__
attribute.
In other words, type
is the factory method creating python classes.
The class creation process
The class creation process can be customized by passing the metaclass
keyword argument in the class definition line, or by inheriting from an existing class that included such an argument. In the following example, both MyClass
and MySubclass
are instances of Meta
:
|
|
Any other keyword arguments that are specified in the class definition are passed through to all metaclass operations described below.
When a class definition is executed, the following steps occur:
- MRO entries are resolved;
- the appropriate metaclass is determined;
- the class namespace is prepared;
- the class body is executed;
- the class object is created.
Here comes our leading role: metaclass, the following is captured from what are metaclasses in python:
Metaclasses are the ‘stuff’ that creates classes.
You define classes in order to create objects, right?
But we learned that Python classes are objects.
Well, metaclasses are what create these objects. They are the classes’ classes, you can picture them this way:
|
|
You’ve seen that type lets you do something like this:
|
|
It’s because the function type
is in fact a metaclass. type
is the metaclass Python uses to create all classes behind the scenes.
Everything, and I mean everything, is an object in Python. That includes integers, strings, functions and classes. All of them are objects. And all of them have been created from a class:
|
|
Now, what is the __class__
of any __class__
?
|
|
So, a metaclass is just the stuff that creates class objects.
You can call it a ‘class factory’ if you wish.
type
is the built-in metaclass Python uses, but of course, you can create your own metaclass.
Use metaclass
First we see an example:
|
|
we see the memory when hit the following breakpoint,
From the picture we see:
- the class name ‘D’ is passed as parameter
cls_name
ofMyMeta.__new__
, - the class variables of
D
is passed as parameterattrs
ofMyMeta.__new__
, - the keyword arguments of
D
–foo
andbar
are passed as keyword arguments ofMyMeta.__new__
.
The next breakpoint: gives
- the
self
variable passed toMyMeta.__call__
is just the classD
, - the
D(3, 4)
pass 3, 4 to parameterargs
ofMyMeta.__call__
.
The last breakpoint gives the memory of instance d
,
- the class
D
has class attributes ‘AAA’ and ‘BBB’, which are converted to uppercase inMyMeta.__new__
, - the instance
d
has instance attributes ‘a=9’ and ‘b=16’, which are processed inMyMeta.__call__
, - console outputs the log of uppercase conversion.
Last word: i highly recommend you to read the document of obj.__new__
and obj.__init__
, and to be continued…