元类补充

什么是元类 ?

基于python的宗旨:一切皆对象。而对象都是由类实例化得到的

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

eval: used to perform simple expression, you can not have any special syntax

How to perform a piece of the inner code and string to the name of the space generated corresponding parameters? >>>    Exec ()

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
"""

 

自定义元类控制类创建的过程

1.如何自定义元类

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  

 

Then the next I need to manually buckle down to these three things the 

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

 

Guess you like

Origin www.cnblogs.com/HZLS/p/11079209.html