[directory]
1, What is metaclass
2, How classes are generated -- the process of creating classes by keyword class
3, How to customize metaclasses to control the generation of classes
4, Built in method__
5, Call of custom metaclass control class
6, Revisit - attribute search
1, What is metaclass
Everything comes from one sentence: everything is the object
#Metaclasses are classes that are used to instantiate generated classes
#Relationship: metaclass - instantiation - > class (People) - instantiation - > object (obj)
class People: def __init__(self,name,age): self.name=name self.age=age def say(self): print('%s:%s' %(self.name,self.name)) print(People.__dict__) # How to get objects # obj=Calling class() obj=People('egon',18) print(type(obj)) # If a class is also an object # People=Calling class(. . . ) # To view built-in metaclasses: # 1,type Is a built-in metaclass # 2,We use class All classes defined by keyword and built-in classes are metaclasses type Instantiation generation print(type(People)) print(type(int))
2, How classes are generated -- the process of creating classes by keyword class
Class has three characteristics: class name, base class and class body
Class has three characteristics: # 1,Class name class_name="People" # 2,Class base class class_bases=(object,) # 3,Execute the class body code to get the class namespace class_dic={} class_body=""" def __init__(self,name,age): self.name=name self.age=age def say(self): print('%s:%s' %(self.name,self.name)) """ exec(class_body,{},class_dic) # print(class_dic) # 4,Call meta class People=type(class_name,class_bases,class_dic)
3, How to customize metaclasses to control the generation of classes
class Mymeta(type): # Only inherited type Class is metaclass # Empty object,"People",(),{...} def __init__(self,x,y,z): print('run22222222222....') print(self) # print(x) # print(y) # print(z) # print(y) # if not x.istitle(): # raise NameError('The first letter of class name must be capitalized!!!') # The current class, the parameter passed in when calling the class def __new__(cls, *args, **kwargs): # make Mymeta Object print('run1111111111.....') # print(cls,args,kwargs) # return super().__new__(cls,*args, **kwargs) return type.__new__(cls,*args, **kwargs) People=Mymeta("People",(object,),{...}) # call Mymeta Three things happen, call Mymeta Namely type.__call__ # 1,Make an empty object first=>People,call Mymeta Intra class__new__Method # 2,call Mymeta In this class__init__Method to complete the operation of initializing the object # 3,Return the initialized object class People(metaclass=Mymeta): def __init__(self,name,age): self.name=name self.age=age def say(self): print('%s:%s' %(self.name,self.name))
Emphasize:
As long as it is a calling class, it will be called once
1. new in class__
2. Within class__
4, Built in method__
class Foo: def __init__(self,x,y): self.x=x self.y=y # obj,1,2,3,a=4,b=5,c=6 def __call__(self,*args,**kwargs): print('===>',args,kwargs) return 123 obj=Foo(111,222) # print(obj) # obj.__str__ res=obj(1,2,3,a=4,b=5,c=6) # res=obj.__call__() print(res)
Application: if you want an object to be call ed with parentheses, you need to add a method \__
Conclusion:
Object () - > call in class__
Class () - > call in custom metaclass__
Custom metaclass () - > built in metaclass__
5, Call of custom metaclass control class
class Mymeta(type): # Only inherited type Class is metaclass def __call__(self, *args, **kwargs): # 1,Mymeta.__call__Function will be called first People Internal__new__ people_obj=self.__new__(self) # 2,Mymeta.__call__Call in function People Internal__init__ self.__init__(people_obj,*args, **kwargs) # print('people Object's properties:',people_obj.__dict__) people_obj.__dict__['xxxxx']=11111 # 3,Mymeta.__call__An initialized object will be returned in the function return people_obj # Generation of classes # People=Mymeta()=>type.__call__=>Did three things # 1,type.__call__Function will be called first Mymeta Internal__new__ # 2,type.__call__Call in function Mymeta Internal__init__ # 3,type.__call__An initialized object will be returned in the function class People(metaclass=Mymeta): def __init__(self,name,age): self.name=name self.age=age def say(self): print('%s:%s' %(self.name,self.name)) def __new__(cls, *args, **kwargs): # Produce real objects return object.__new__(cls) # Class calls # obj=People('egon',18) =>Mymeta.__call__=>Did three things # 1,Mymeta.__call__Function will be called first People Internal__new__ # 2,Mymeta.__call__Call in function People Internal__init__ # 3,Mymeta.__call__An initialized object will be returned in the function obj1=People('egon',18) obj2=People('egon',18) # print(obj) print(obj1.__dict__) print(obj2.__dict__)
6, Revisit - attribute search
#Principle of attribute search: object class parent class
#Remember: the parent class is not a metaclass
class Mymeta(type): n=444 def __call__(self, *args, **kwargs): #self=<class '__main__.StanfordTeacher'> obj=self.__new__(self) # StanfordTeacher.__new__ # obj=object.__new__(self) print(self.__new__ is object.__new__) #True self.__init__(obj,*args,**kwargs) return obj class Bar(object): # n=333 # def __new__(cls, *args, **kwargs): # print('Bar.__new__') pass class Foo(Bar): # n=222 # def __new__(cls, *args, **kwargs): # print('Foo.__new__') pass class StanfordTeacher(Foo,metaclass=Mymeta): # n=111 def __init__(self,name,age): self.name=name self.age=age obj=StanfordTeacher('lili',18) print(obj.__dict__) # print(obj.n) # print(StanfordTeacher.n)
reference material: