[2020Python cultivation] object oriented programming -- metaclass

Posted by Timsoft on Wed, 15 Apr 2020 16:51:59 +0200

[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:

https://zhuanlan.zhihu.com/p/109336845

https://www.cnblogs.com/linhaifeng/articles/6204014.html

Topics: Python Attribute