Python's meta-class explanation

Source: Internet
Author: User

First, the Primer

Meta-class belongs to the Python object-oriented programming of the Deep magic, 99% of people are no avail, some think to understand the meta-class is actually also justified, donuts, from the team of the control of the meta-flawed, logic confusion;

Second, what is the meta-class

It all comes down to a sentence: everything in Python is an object. Let's first define a class and then step through the analysis

#!/usr/bin/env python# -*- coding: utf-8 -*-class MyTeacher(object):    school='john'    def __init__(self,name,age):        self.name = name        self.age =age    def say(self):        print('%s says welcome to the john to learn Python' %self.name)

All objects are instantiated or called classes (the process of calling a class is called instantiation of the Class), such as the object T1 is the myteacher of the calling class.

t1 = MyTeacher('zhangsan',18)print(type(t1))   # 查看对象t1的类是<class '__main__.MyTeacher'>

If everything is an object, then the myteacher nature of the class is an object, since all objects are obtained by invoking the class, then Myteacher must also be called Class One class, this class is called 元类 ;

So we can push the export---> the process of generating myteacher must have occurred: myteacher= meta-class (...)

print(type(MyTeacher))    # 结果为<class 'type'>,证明是调用类type这个元类产生的MyTeacher,即默认的元类为type

Third, class keyword creation of the process analysis

Above, we analyze everything in python based on the concept of object: The class we define with the class keyword is itself an object, the class that produces the object is called a meta class (the Meta class can be called Class), and the built-in meta-class istype

classKeyword to help us create the class, it is necessary to help us call the class meta-class MyTeacher=type(...) , that call type when the parameters passed in? Must be a key component of a class, with three main components, namely:

    • Class name Class_name= ' Myteacher '
    • Base class Class_bases= (object,)
    • The namespace of the class is class_dic, and the namespace of the class is obtained by executing the class body code

When the type is called, the above three parameters are passed in sequence

General, class keyword help us create a category that should be subdivided into four processes:

Iv. usage of EXEC
#!/usr/bin/env python# -*- coding: utf-8 -*-# exec:三个参数# 参数一:包含一系列Python的字符串# 参数二:全局作用域(字典形式),如果不指定,默认为globals()# 参数三:局部作用域(字典形式),如果不指定,默认为locals()# 可以把exec命令的执行当成一个函数的执行,会将执行期间产生的名字存放于局部名称空间中g={    'x':1,    'y':2}l={}exec('''global x,zx=100z=200m=300''',g,l)print(g) #{'x': 100, 'y': 2,'z':200,......}print(l) #{'m': 300}
V. Creation of custom meta-class control class Myteacher

A class does not declare its own meta-class, and by default his meta-class type, in addition to using the built-in meta-class type, we can also customize the meta-class by inheriting the type, and then using mataclass the keyword argument to specify the meta-class for a class

#!/usr/bin/env python# -*- coding: utf-8 -*-class Mymeta(type):  # 只有继承类type类才能称之为一个元类,否则就是一个普通自定义类    passclass MyTeacher(object,metaclass=Mymeta): # MyTeacher=Mymeta('MyTeacher',(object),{...})    school = 'john'    def __init__(self,name,age):        self.name = name        self.age = age    def say(self):        print('%s says welcome to the zhangsan to learn Python' %self.name)        

The

Custom meta-class can control the generation of the class, which is actually the process of calling the Meta class, that is, Myteacher=mymeta (' Myteacher ', (object), {...}), and calling Mymeta first produces an empty object Myteacher, The __init__ method is then passed to Mymeta with the parameters in the call Mymeta parentheses, which completes the initialization, so we can

Class Mymeta (Type): #只有继承了type类才能称之为一个元类, otherwise a normal custom class Def __init__ (self,class_name,class_bases,class_dic): # PR int (self) #<class ' __main__. Myteacher ' > # print (class_bases) # (<class ' object ';,) # Print (class_dic) #{' __module__ ': ' __main__ ' , ' __qualname__ ': ' Myteacher ', ' School ': ' My ', ' __init__ ': <function myteacher.__init__ at 0x102b95ae8> ' Say ': &lt function Myteacher.say at 0x10621c6a8>} super (Mymeta, self). __init__ (Class_name, Class_bases, Class_dic) # reusing parent function of the class if Class_name.islower (): Raise TypeError (' class name%s please modify as Camel body '%class_name) if ' __doc__ ' not in Clas S_dic or Len (class_dic[' __doc__ '].strip (' \ n ')) = = 0:raise TypeError (' The class must have a document comment and the document comment cannot be null ') class Myteacher (ob    Ject,metaclass=mymeta): # Myteacher=mymeta (' Myteacher ', (object), {...})    Document Comment "" "Class Myteacher" "School= ' My ' def __init__ (self,name,age): Self.name=name self.age=age Def say (self): print ('%s says WelcoMe to the Learn Python '%self.name) 
Vi. custom meta-class control calls to class Myteacher

Reserve Knowledge: Call

#!/usr/bin/env python# -*- coding: utf-8 -*-class Foo:    def __new__(self, *args, **kwargs):        print(self)        print(args)        print(kwargs)obj = Foo()# 1. 要想让obj这个对象变成一个可调用的对象,需要在该对象的类中定义一个方法__call__方法,该方法会调用对象时自动触发# 2. 调用obj的返回值就是__call__方法的返回值res=obj(1,2,3,x=1,y=2)

It is learned from the above example that invoking an object is the execution of the __call__ method in the class that triggers the object, and if Myteacher is also treated as an object, then there must be a __call__ method in the class of Myteacher object.

class Mymeta(type): # 只有继承类type类才能称为一个元类,否则就是一个普通的自定义类    def __call__(self, *args, **kwargs):        print(self)  # <class '__main__.MyTeacher'>        print(args)  # ('zhangsan', 18)        print(kwargs)  # {}        return 123class MyTeacher(object,metaclass=Mymeta):    school = 'john'    def __init__(self,name,age):        self.name = name        self.age = age    def say(self):        print('%s says welcome to the john to learn Python' %self.name)# 调用MyTeacher就是在调用Myteacher类中__call__方法# 然后将MyTeacher传给self,益出的位置参数传给*,益出的关键字参数传给**# 调用MyTeacher的返回值就是调用__call__的返回值t1 = MyTeacher('zhangsan',18)print(t1)  # 123

By default, calling T1=myteacher (' Zhangsan ', 18) will do three things

    1. Produces an empty object, obj
    2. Call the __init__ method to initialize the object obj
    3. Returns the initial good obj

Correspondingly, the __call__ method in the Myteacher class should also do these three things

class Mymeate(type):  # 只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类    def __call__(self, *args, **kwargs):  # self=<class '__main__.MyTeacher'>        # 1. 调用__new__ 产生类一个空对象obj        obj = self.__new__(self) # 此处的self是类MyTeacher,必须传参,代表创建一个MyTeacher的对象obj        # 2. 调用__init__初始化空对象obj        self.__init__(obj,*args,**kwargs)        # 3. 返回初始化好的对象obj        return objclass MyTeacher(object,metaclass=Mymeate):    school = 'john'    def __init__(self,name,age):        self.name = name        self.age = age    def say(self):        print('%s says welcome to the john to learn Python' %self.name)t1 = MyTeacher('zhangsan',18)print(t1.__dict__)  # {'name': 'zhangsan', 'age': 18}

The __call__ of the example above is equivalent to a template, and we can rewrite the __call__ logic on that basis to control the process of invoking Myteacher.
For example, all the properties of an Myteacher object are changed to private.

class Mymeta(type):  # 只有继承类type类才能称之为一个元类,否则就是一个普通的自定义    def __call__(self, *args, **kwargs):   # self=<class '__main__.MyTeacher'>        obj=self.__new__(self)  # 此处的self是类MyTeacher,必须传参,代表创建一个MyTeacher的对象obj        # 2. 调用__init__初始化空对象obj        self.__init__(obj,*args,**kwargs)        # 在初始化之后,obj.__dict__里就有值了        obj.__dict__ = {'_%s__%s' % (self.__name__, k): v for k, v in obj.__dict__.items()}        #3、返回初始化好的对象obj        return objclass MyTeacher(object,metaclass=Mymeta):    school = 'john'    def __init__(self,name,age):        self.name = name        self.age = age    def say(self):        print('%s says welcome to the john to learn Python' %self.name)t1=MyTeacher('zhangsan',18)print(t1.__dict__)   # {'_MyTeacher__name': 'zhangsan', '_MyTeacher__age': 18}
Six, look again attribute search

Combining the implementation principle of Python inheritance + meta-class re-look at the properties of the search should be what it looks like???

In fact, we use class custom classes are all objects (including the object class itself is also an instance of the meta-class type, can be viewed with type (object), if the class as an object, the following inheritance should be said to be: objects with myteacher inherit the object foo, Object Foo Inherits object bar, object bar Inherits Object

class Mymeta(type):  # 只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类    n = 444    def __call__(self, *args, **kwargs): #self=<class '__main__.MyTeacher'>        obj=self.__new__(self)        self.__init__(obj,*args,**kwargs)        return objclass Bar(object):    n = 333class Foo(Bar):    n = 222class MyTeacher(Foo,metaclass=Mymeta):    n = 111    school = 'john'    def __init__(self,name,age):        self.name = name        self.age = age    def say(self):        print('%s says welcome to the john to learn Python' % self.name)print(MyTeacher.n)  #自下而上依次注释各个类中的n=xxx,然后重新运行程序,发现n的查找顺序为MyTeacher->Foo->Bar->object->Mymeta->type

Summary: Mymeta under the __call__ in the self.__new__ in Myteacher,foo,bar did not find __new__ case, will go to find object in __new__, and object under the default there is a __new__, So even if the previous class did not implement __NEW__, will certainly find a in the object, there is no, there is no need to find the meta-class Mymeta-->type find __new__

Python's meta-class explanation

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.