What is a metaclass in python

Simply put, dollar class creates all the objects in Python.

We say that Python is a dynamic language, but the biggest difference between dynamic and static languages, is the definition of functions and classes are not compiled, but dynamically created runtime .

Let's say we want to define one HelloWorldof the class, write a helloworld.pymodule:

class HelloWorld(object):
    def helloworld(self):
        print('Hello World!')

When the Python interpreter is loaded helloworldwhen the module will turn all statements in this module, the execution result is a dynamically created HelloWorldclass object of the test is as follows:

>>> from helloworld import HelloWorld
>>> h = HelloWorld()
>>> h.helloworld()
Hello, world!
>>> print(type(HelloWorld))
<class 'type'>
>>> print(type(h))
<class 'helloworld.HelloWorld'>

type()Function is used to view a type or variable type HelloWorldis a class, that is, its type type, and his an example, it is the type of class  Helloworld.

We say that the class definition is dynamically created at runtime, and create a class of methods is to use the type()function .

Definitions: of the type (class name ,  a tuple of the parent class (for the case of inheritance, can be empty), contains the attributes dictionary (names and values) )

type()Function returns an object of either type, and can create a new type, for example, we can type()create a function HelloWorldclass without going through a class HelloWorld(object)...definition:

>>> def helloworld_outside(self): # 先定义函数
...     print('Hello World!')
...
>>> HelloWorld = type('HelloWorld', (object,), dict(helloworld=helloworld_outside)) # 创建HelloWorld class
>>> h = HelloWorld()
>>> h.helloworld()
Hello, world!
>>> print(type(HelloWorld))
<class 'type'>
>>> print(type(h))
<class '__main__.HelloWorld'>

So you want to create a class object, type()the function passed in turn requires three parameters:

  1. class name;
  2. Inherit parent collections, pay attention to Python supports multiple inheritance, if only one parent, do not forget the single-element tuple writing;
  3. class method name and function bindings, here we have a function helloworld_outside bound to the name of the method helloworldon.

Through type()classes and direct write class is exactly the same function to create , because Python interpreter encounters the definition of class time, just scan the grammar class definition, and then call the type()function to create a class.

Under normal circumstances, we are used class Xxx...to define the class, however, type()function also allows us to dynamically create a class, that is, the dynamic language runtime support itself dynamically create classes, and static languages which have a very big difference to the static Creating language runtime classes, you must construct a string and then calls the source code compiler, or use some tools to generate bytecode, are essentially dynamic compilation, it will be very complicated.

metaclass

In addition to using type()outside dynamically create a class, to control the behavior of the class is created, you can also use the metaclass that .

metaclass, literally translated as metaclasses, the explanation is simple:

When we define the class later, you can create an instance of this class in accordance with, so: first define the class and create an instance.

But if we want to create a class of it? You must create a class based on metaclass, so: define metaclass, and then create a class .

Therefore, the metaclass that allows you to create or modify class category. In other words, you can create out of class as a metaclass "instance."

object-oriented Python metaclass is most difficult to understand, magic code that is most difficult to use. Under normal circumstances, you will not run into situations require the use of metaclass, therefore, the following can not read does not matter, because basically you will not use.

We look at a simple example, this metaclass can give our custom MyList add a addmethod:

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 are the results, test MyListwhether you can call the add()method:

>>> L = MyList()
>>> L.add(1)
>> L
[1]

Through this example we can see our custom MyList two steps:

1. Create Metaclass, to create / modify classes

2. Create the actual MyList Class

First we look at the first step, create Metaclass:

class ListMetaclass(type):
    def __new__(cls, name, bases, attrs):
        attrs['add'] = lambda self, value: self.append(value)
        return type.__new__(cls, name, bases, attrs)

  • The definition of the class name : the definition ListMetaclass, in accordance with the customary default, metaclass class name always ends with Metaclass, in order to clearly indicate that this is a metaclass
  • Metaclass parent class : Metaclass是类的模板,所以必须从`type`类型派生:
  • Select __new__ function as functions "Modify Class" :
    • Function __new __ (cls, name, bases, attrs) in, "cls" similar to a class in self arguments to other functions, such as __init __ (self), but the object is created on behalf of self, and cls represents the class itself (__init__ as an example initialization function, you need to pass as an argument into the instance itself, so that we can guarantee to be modified is an example; the same token, __ new__ function needs to pass the class itself as an argument into account, in order to ensure that the current class is initialized); name representative of the name of the class; Representative bases parent class of the current class set; attrs attribute representing the current class, the narrow sense is a set of attributes and methods, can be passed by way dictionary dict
    • __New__ definition of DEF  __new__ (CLS, name, bases, attrs), in fact, "new" is true in Python constructor (creates and returns an instance), it can be produced by this method a "cls" corresponds the instance of an object so that the "new" method must have a return, should create an object instance is returned back. Here, we modified the class into __new__ process, and returns an instance of the object after the modification. In addition, a very simple reason, select the type .__ new__ as a function of the return value, because our ListMetaclass inherited from type, and therefore should return the object class type of function __new__ created.
class MyList(list, metaclass=ListMetaclass):
    pass

With ListMetaclass, the next question is how to use ListMetaclass?

First, we need to talk about Python's class mechanism created:

When creating the class, python will first check the current class has no __metaclass__, if any, to use this method to create an object; if not, it will check the parent of a level there is no __metaclass__, to create object. Create this "object" is the current class. If the current class and the parent class are not, it will look for __metaclass__ method in the current package, if not, it will call its own hidden function to create an object of type .

It is noteworthy that, if we do define the class, passing in a keyword in the class declaration metaclass = ListMetaclass at, so if there is an incoming __call__ this metaclass function, this function will overwrite __call__ MyList class the __new__ function. Why is this? Please recall that when we instantiate MyList, the use of the statement is L1 = MyList (), and we know __ role call__ function is to make the object after the class is instantiated can be like a function call. That is the object MyList after ListMetaclass instantiated, but MyList () call is ListMetaclass of __call__ function. In addition, it is worth mentioning that, if declared at the class, we let MyList inherited ListMetaclass, then ListMetaclass of __call__ function will not overwrite the __new__ MyList function.

Therefore, we have to use ListMetaclass instructions to customize the class in a class definition (that is, when MyList class definition, keyword arguments passed in at the class declarationmetaclass=ListMetaclass):我们传入关键字参数metaclass后,python会在当前class里创建属性__metaclass__,因此它指示Python解释器在创建MyList时,要通过ListMetaclass.__new__()来创建,在ListMetaclass.__new__()中,我们可以修改类的定义,比如,加上新的方法,然后,返回修改后的定义。

Ok, the following test MyListif you can call the add()method:

>>> L = MyList()
>>> L.add(1)
>> L
[1]

And ordinary listno add()method:

>>> L2 = list()
>>> L2.add(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute 'add'

What is the significance of dynamic modification? Directly in the MyListdefinition of the write add()method is not more simple? Under normal circumstances, it should really be written directly by modifying metaclass purely metamorphosis.

However, there will always need to modify the class definition of the metaclass . ORM is a typical example.

ORM stands for "Object Relational Mapping", that is, the object - relational mapping is mapped to a relational database row as an object, which is a class corresponds to a table, so, write code more simple, do not directly manipulate SQL statements.

Guess you like

Origin www.cnblogs.com/NumerOne/p/11689907.html