zoukankan      html  css  js  c++  java
  • 元类

    什么是元类

    因为在python中一切皆对象,类实际上就是一个一个的类

    type是内置的一个元类,所有的类都是由type实例化得到

    class Person:
        def __init__(self,name):
            self.name=name
        def score(self):
            print('分数是100')
    
    p=Person('nick')
    

    如Person类也是个对象,那他一定是由一个类实例化得到,这个类,就叫元类

    同理:type类是产生所有类的元类

    class底层原理

    通过type来直接产生类,不用class关键字了

    l ={}
    exec('''
    school = 'oldboy'
    def __init__(self,name):
        self.name= name
    
    def score(self):
        print('分数是100')
    
    ''',{},l)
    
    Person = type('Person',(object,),l)  ##type产生的类
    print(Person.__bases__)
    #   ->(<class 'object'>,)
    p = Person('nick')
    print(p.name)
    #   ->nick
    

    class 底层就是调用type来实例化产生类(对象)

    Person 类是由type实例化产生,传一堆参数

    自定义元类控制类的产生

    自定义元类:来控制类的产生:可以控制类名,可以控制类的继承父类,控制类的名称空间

    自定义元类必须继承type>>>

    class Mymeta(type):
    
        #type(name, bases, dict) -> a new type
        def __init__(self,name,bases,dic):
            print(name)
            print(bases)
            print(dic)
    
    class Person(object,metaclass=Mymeta):
    
    #当python解释器遇到metaclass会去使用Mymeta去创建这个类
    #这里可以把person类看成一个对象
    
        school = 'heima'
        def __init__(self,name):
            self.name = name
        def score(self):
            print('分数是100')
    
    p = Person('nick')
    print(p.name)
    
    结果:
        
    # -> Person
    # ->(<class 'object'>,)
    # ->{'__module__': '__main__', '__qualname__': 'Person', 'school': 'heima', '__init__': <function Person.__init__ at 0x0000028A31973EA0>, 'score': <function Person.score at 0x0000028A31973F28>}
    # ->nick
    

    通过元类控制类的调用过程

    控制类的调用过程,实际上在控制:对象的产生

    # 触发元类的__call__,无法调用p.name
    
    class Mymeta(type):
        def __call__(self, *args, **kwargs):
            # print('xxx')
    
            return 1
    
    class Person(object,metaclass=Mymeta):
        school='zheda'
        def __init__(self,name):
            self.name=name
        def score(self):
            print('分数是100')
    
    p=Person('nick')
    print(p)
    # print(p.name)  ->报错
    
    结果:1
    
    

    _new_

    __new__方法(第一个执行)先于__init__方法执行

    __new__方法是传入类(cls),而__init__方法传入类的实例化对象(self),而有意思的是,__new__方法返回的值就是一个实例化对象(ps:如果__new__方法返回None,则__init__方法不会被执行,并且返回值只能调用父类中的__new__方法,而不能调用毫无关系的类的__new__方法)。

    class A:
        pass
    
    
    class B(A):
        def __new__(cls):
            print("__new__方法被执行")
            return cls.__new__(cls)
    
        def __init__(self):
            print("__init__方法被执行")
    
    
    b = B()
    
    #注意:new() 函数只能用于从object继承的新式类。
    

    有了元类后的属性查找

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

    1.类的属性查找顺序:先从类本身中找--->mro继承关系去父类中找---->去自己定义的元类中找--->type中--->报错
    2.对象的属性查找顺序:先从对象自身找--->类中找--->mro继承关系去父类中找--->报错

  • 相关阅读:
    DZY Loves Sequences
    Boredom easy dp
    floyd算法 poj1125
    poj3259 Bellman_Ford算法
    poj1860 Bellman_Ford算法
    Java 获取资源文件路径
    CLion 2020.1.2 激活
    Kotlin学习笔记
    Kotlin Hello World
    WebStorm 2020.1.2 激活
  • 原文地址:https://www.cnblogs.com/qwksjy/p/11453709.html
Copyright © 2011-2022 走看看