Simply put, the meta-class creates all the objects in Python.
We say that Python is a dynamic language, and the biggest difference between dynamic and static languages is that functions and classes are not defined at compile time, but are created dynamically at runtime.
For example, if we want to define a HelloWorld
class, we write a helloworld.py
module:
class HelloWorld (object): def HelloWorld (self): print('Hello world! ')
When the Python interpreter loads the helloworld
module, it executes all the statements of that module sequentially, and the result is a dynamically created HelloWorld
class object, which is tested as follows:
>>> from helloworld import Span style= "COLOR: #000000" > HelloWorld >>> h = HelloWorld () > >> H.helloworld () Hello, world! >>> print (type (HelloWorld)) <class " type " >>>> print (Type (h)) <class " helloworld. HelloWorld ";
type()
The function is used to see the type of a type or variable, HelloWorld
is a class, and its type is type
h
an instance, and its type is class Helloworld
.
We say that the definition of class is created dynamically at runtime, and the method of creating class is to use type()
functions.
Definition: Type(class name , tuple of parent class (can be empty for inheritance), Dictionary containing property (name and value))
type()
A function can either return the type of an object, or create a new type, for example, we can type()
create a class from a function without HelloWorld
having to pass class HelloWorld(object)...
the definition:
>>>defHelloworld_outside (self):#define the function first...Print('Hello world!')...>>> HelloWorld = Type ('HelloWorld', (object,), Dict (Helloworld=helloworld_outside))#Create HelloWorld class>>> h =HelloWorld ()>>>H.helloworld () Hello, world!>>>Print(Type (HelloWorld))<class 'type'>>>>Print(Type (h))<class '__main__. HelloWorld'>
So to create a class object, the type()
function needs to pass in 3 arguments in turn:
- The name of the class;
- Inherited parent class Collection, note that Python supports multiple inheritance, if there is only one parent class, do not forget the single element of tuple notation;
- Class's method name and function binding, where we bind the function Helloworld_outside to the method name
helloworld
.
The type()
class created by the function is exactly the same as the direct write class, because when the Python interpreter encounters the class definition, it simply scans the syntax of the class definition and then invokes type()
the function to create the class.
Normally, we use class Xxx...
to define the class, but the type()
function also allows us to dynamically create the class, that is, the dynamic language itself supports the runtime dynamic creation of classes, which is very different from static language, to create a class in the static language runtime, you must construct the source code string and then call the compiler, Or the use of some tools to generate bytecode implementations, essentially dynamic compilation, can be very complex.
Metaclass
In addition type()
to using dynamically created classes, you can also use Metaclass to control the creation behavior of classes.
Metaclass, literal translation is a meta-class, the simple explanation is:
Once we have defined the class, we can create an instance from this class, so: Define the class first, and then create the instance.
But what if we want to create a class? Then you must create the class from Metaclass, so define the Metaclass first, and then create the class.
So, Metaclass allows you to create classes or modify classes. In other words, you can think of a class as an "instance" created by Metaclass.
Metaclass is the most difficult and difficult-to-use magic code for Python-oriented objects. Under normal circumstances, you will not encounter the need to use metaclass situation, so, the following can not understand it is OK, because basically you will not use.
Let's look at a simple example where this metaclass can add a method to our custom MyList add
:
class Listmetaclass (type): def __new__ (CLS, name, bases, attrs): attrs['add'lambda self , value: Self.append (value) return type. __new__ (CLS, name, bases, Attrs) class MyList (list, metaclass=listmetaclass): Pass
Here is the result of the run and test MyList
whether the method can be called add()
:
>>> L = MyList ()>>> l.add (1)>> l[1]
With this example we can see that customizing our mylist is two steps:
1. Create Metaclass to create/modify classes
2. Create the actual mylist Class
First we take a look at the first step, creating Metaclass:
- Definition of the class name: Defined
ListMetaclass
, according to the default habit, the class name of Metaclass always ends with metaclass so that it is clear that this is a metaclass
- Metaclass's parent class: M
etaclass是类的模板,所以必须从`type`类型派生:
Select the __NEW__ function as the function that implements the Modify class:
- The definition of __new__ is generally:def __new__(CLS, name,bases,attrs), in fact, the "New" method is the real construction method in Python (creating and returning instances) , this method can produce a "CLS" corresponding to the instance object so that the "new" method must have a return, to the created instance object back. Here, we put the modification of the class into the __new__ method, and then return the modified instance object. In addition, it is very simple to choose the type.__new__ function as the return value because our Listmetaclass inherits from type, so we should return the object created by the __NEW__ function of class type.
- In addition, in function __new__ (CLS, name,bases,attrs), the "CLS" is similar to the self parameter of other functions in the class, such as __init__, except that the CLS stands for the class itself, and that is the object that is created; The name represents the names of the classes, bases represents the collection of parent classes for the current class, Attrs represents the properties of the current class, is a collection of properties and methods in the narrow sense, and can be passed in as a dictionary dict
class Listmetaclass (type): def __new__ (CLS, name, bases, attrs): attrs['add'lambda self , value: Self.append (value) return type. __new__ (CLS, name, bases, Attrs)
With Listmetaclass, we also instruct the class to use Listmetaclass to customize the class, passing the keyword argumentmetaclass,当我们传入关键字参数metaclass
时,它指示Python解释器在创建MyList
时,要通过ListMetaclass.__new__()
来创建,在ListMetaclass.__new__()中,我们可以修改类的定义,比如,加上新的方法,然后,返回修改后的定义。
So why is the keyword parameter passed inmetaclass,就指示Python解释器在创建MyList
时,要通过ListMetaclass.__new__()
来创建呢?
In fact, when the keyword parameter metaclass is passed in, Python creates an attribute __metaclass__ in the current class.
When the class is created, Python checks that there are no __metaclass__ in the current class, and if so, creates the object using this method, and if not, the first-level check that there is no __metaclass__ in the parent class to create the object. The "object" that is created is the current class. If neither the current class nor the parent class is present, the __metaclass__ method is found in the current package, and if not, the object is created by calling its own hidden type function.
class MyList (list, metaclass=listmetaclass): Pass
Test MyList
Whether the method can be called add()
:
>>> L = MyList ()>>> l.add (1)>> l[1]
list
there is no ordinary add()
way:
>>> L2 = list ()>>> l2.add (1) Traceback (most recent call last): " <stdin>" in <module>'list ' Add '
What is the meaning of dynamic modification? MyList
isn't it easier to write the method directly in the definition add()
? Under normal circumstances, it should be written directly, through metaclass modification is purely perverted.
However, you will always encounter the need to modify the class definition through Metaclass. ORM is a typical example.
ORM Full Name "Object Relational Mapping", that is, object-relational mapping, is to map a row of the relational database to an object, that is, a class corresponding to a table, so that the code is simpler to write, do not directly manipulate the SQL statement.
I'll talk more about how ORM works in the next article.
Talk about the meta-class metaclass in Python (a): What is a meta-class