什么是元类 ?
class OldboyTeacher(object): school = 'oldboy' def __init__(self,name): self.name = name def run(self): print('%s is running'%self.name) t1 = OldboyTeacher('jason')
# 对象t1是由类OldboyTeacher实例化得到
那么类也是对象,它又是谁实例化得到的呢?
# Each view object type t1 and OldboyTeacher Print (type (t1)) Print (type (OldboyTeacher)) # results: < class ' . OldboyTeacher in __main __ ' > < class ' type ' >
Conclusion 1: The meta-class class class is generated, the default is that all class metaclass type of case
It does not depend on the class keyword to create a class
According to the first conclusion we can sort out the correspondence between the two
1. Call metaclass obtain custom class
2. Call custom class objects to get a custom class
Now we look at the first of the relationship, call the Yuan class to get a custom class, which parameters are required (OldboyTeacher = type (...), what passed in parentheses?)
We customize a class when what are the key components:
1. The name of the class
2. super class
3. namespace class
Take OldboyTeacher class first stage, for example, steps to create a custom class calss keyword
"" " 1. Get Class Name (OldboyTeacher) parent 2. Get class (Object,) 3. execute the code based body obtain namespace generated (How to obtain ???) 4. Call metaclass obtain custom class OldboyTeacher type = (class_name, class_bases, {...}) "" "
Supplementary exec
exec: python for carrying out a string of code that can be executed that they meet the python, and you can specify the name of the execution generated into a name space
class_body = """ school = 'oldboy' def __init__(self,name): self.name = name def run(self): print('%s is running'%self.name) """ class_dic = {} class_global = {} exec(class_body,class_global,class_dic) # class_global一般情况下都为空,除非在字符串代码内部用global关键字声明,才会将产生的名字丢到class_global全局名称空间中 print(class_dic) {'school': 'oldboy', '__init__': <function __init__ at 0x000000B5D2771EA0>, 'run': <function run at 0x000000B5DB5B7400>}
有了这个exec方法后,我们就可以不依赖于calss关键字创建自定义类
# Class name class_name = ' OldgirlTeacher ' # super class class_bases = (Object,) # attention must be Ganso, a comma can not forget # namespace class_body = "" " School = 'oldgirl' DEF __init __ (Self, name): Self name = .name DEF RUN (self): Print (the self.name) "" " class_dic = {} Exec (class_body, {}, class_dic) # call metaclass create custom classes OldgirlTeacher = type (class_name, class_bases, class_dic) Print (OldgirlTeacher) # results: <class 'in __main OldgirlTeacher __.'> # 并且它可以访问自身的属性和方法,并实例化产生对象 print(OldgirlTeacher.school) print(OldgirlTeacher.run) # 结果为: """ oldgirl <function run at 0x000000229B157378> """ obj = OldgirlTeacher('jason') print(obj.school) obj.run() """ oldgirl jason """
class Mymeta (type): # must be inherited type of class is the custom metaclass Pass class oldboyTeacher (metaclass = Mymeta): # by metaclass metaclass can specify the class of the School = ' Oldboy ' DEF __init__ (Self, name) : the self.name = name DEF RUN (Self): Print ( ' % S running IS ' % the self.name)
2.__call__
Thoughts: The object of a class brackets will execute __call__ method calls the object's parent class, the class is also object that in brackets when instantiating an object, is not it also should go __call_ methods of its parent class ?
class Mymeta(type): def __call__(self, *args, **kwargs): print(self) print(args) print(kwargs) class OldboyTeacher(object,metaclass=Mymeta): school = 'oldboy' def __init__(self,name): self.name = name def run(self): print('%s is running'%self.name) obj = OldboyTeacher('jason') "" " Print Results: <class 'in __main OldboyTeacher __.'> ( 'Jason',) {} " ""
Reflection: class brackets when instantiating the object, is there any steps?
1. Create an empty object class
2. Examples of the empty object
3. Examples of completed space object is returned to the caller
# That __call__ need to do three things which class Mymeta (of the type): DEF __call__ (Self, * args, ** kwargs): # 1. produces empty object # 2 initialize the object # 3. Return the object # The last thing that I do first, a return to 123, found that return 123 obj = OldboyTeacher ( ' Jason ' ) Print (obj) # The result is 123
class Mymeta (type): DEF the __call__ (Self, args *, ** kwargs): # 1. generates an empty object obj = Self. __new__ is (Self) # 2. Examples of the object Self. the __init__ (obj, args *, ** kwargs) # 3. return the object return obj # on this __new__, we do not know is not Gesha, I'm here to tell you, it is used to create an empty object
Thoughts: This is a class of objects produced bracketed process, then the process I metaclass bracketed generated class is not it also should be the three-step
1. an empty object (class means)
2. Examples of the empty object (instance of the class)
3. Examples of the class object is complete return
That based on the above derivation, self .__ new__ is the key, I can define a __new__ method in my custom metaclass inside, take a look at it in the end is Gesha
class Mymeta(type): def __new__(cls, *args, **kwargs): print(cls) print(args) print(kwargs) class OldboyTeacher(object,metaclass=Mymeta): school = 'oldboy' def __init__(self, name): self.name = name def run(self): print('%s is running' % self.name) """ <class '__main__.Mymeta'> ('OldboyTeacher', (object,), {'__module__': '__main__', '__qualname__': 'OldboyTeacher', 'school': 'oldboy', '__init__': <function OldboyTeacher.__init__ at 0x000000323CEB9510>,
'run': <function OldboyTeacher.run at 0x000000323CEE7158>}) {} """
We found __new__ * args parameter received inside the three position parameters are easily identified and their corresponding class is the name of the class parent class, the class code execution thereof namespace
Can we then will __new __ () formal parameters in a different wording
class Mymeta (type): DEF __new__ (CLS, class_name, class_bases, class_dic): Print (class_name) Print (class_bases) Print (class_dic) # It should be remembered that the last call must __new__ in metaclass type of the method of generating the empty object return type. __new__ is (CLS, class_name, class_bases, class_dic) class OldboyTeacher (= the metaclass that Mymeta): School = ' Oldboy ' DEF the __init__ (Self, name): the self.name = name DEF RUN (Self) : Print ('%s is running'%self.name)
verification:
class Mymeta(type): def __new__(cls, class_name,class_bases,class_dic): print(class_name) print(class_bases) print(class_dic) class_dic['xxx'] = '123' if 'school' in class_dic: class_dic['school'] = 'DSB' return type.__new__(cls,class_name,class_bases,class_dic) class OldboyTeacher(metaclass=Mymeta): School = ' Oldboy ' DEF the __init__ (Self, name): the self.name = name DEF RUN (Self): Print ( ' % S running IS ' % the self.name) Print (OldboyTeacher.xxx) # discovery can be printed out of 123 Print (OldboyTeacher.school) # DSB
in conclusion:
From this we can custom yuan class, and override __new__ method to block the creation of the class, a series of other operations before the class is created