• 贰拾叁


    一、元类

    ​ 在python中一切皆对象,所以类也是一个对象,对象是由类实例化产生的,所以类也可以实例化产生。那么实例化产生类的类就是元类。

    class B
    	def __init__(self,v)
    print(type(B))
    
    <class 'type'>
    

    ​ 使用print(type(类))的方法可以找到类的类。

    ​ type为python内置元类,所有的类都是由type实例化产生的。

    二、class底层原理分析

    ​ 平时使用class + 类名的方式将类构造出来,但实际上这些类是由元类实例化产生的。type为python内置元类,类是由type实例化产生,并且传入一堆参数。

    ​ type是使用类的内置__init__方法产生类的。

        # 类的源码
        def __init__(cls, what, bases=None, dict=None): # known special case of type.__init__
            """
            type(object_or_name, bases, dict)
            type(object) -> the object's type
            type(name, bases, dict) -> a new type
            # (copied from class doc)
            """
            pass
    

    ​ 元类通过object_or_name, bases, dict(类名:字符串,父类,名称空间:字典)的方式产生类,可以代替class关键字的方式。

    #通过type来直接产生类,不用class关键字了
    l={}
    exec('''
    school='oldboy'
    def __init__(self,name):
        self.name=name
    def score(self):
        print('分数是100')
    ''',{},l)
    def __init__(self,name):
        self.name=name
    
    # Person=type('Person',(object,),{'school':'oldboy','__init__':__init__})
    #
    Person=type('Person',(object,),l)
    

    三、通过元类控制类的产生

    ​ 通过控制类名,控制类的继承父类,控制类的名称空间的方法自定义元类,由此可以控制类的产生。

    ​ 自定义元类,都要继承type元类。

    class A(type):
    
    class B(metaclass=  A):
    

    ​ metaclass= A指定类B的元类为A。

    ​ 练习:自定义元类,控制类产生,类的名称空间必须要有name字段才能创建成功,否则失败。

    lass Mymeta(type):
        def __init__(self,name):
            if not 'name' in name:
                raise   TypeError('没有name字段')
    
    class Aname(object,metaclass=Mymeta):
        def __init__(self,name):
            self.name = name
    

    四、通过元类控制类的调用

    ​ 通过元类控制类的调用实际上是在控制对象的产生。

    class Mymeta(type):
        def __call__(self, *args, **kwargs):
            # print('xxx')
    
            return 1
    
    class Person(object,metaclass=Mymeta):
        school='oldboy'
        def __init__(self,name):
            self.name=name
        def score(self):
            print('分数是100')
    
    p=Person('nick')
    print(p.name)
    

    ​ 类的调用过程是先触发元类的__call__ ,再触发类的init方法。

    ​ 练习:定义一个元类,定义一个类继承字典,使其具备点取值和赋值功能,通过元类控制对象的产生,把所有属性放在attr字典中,属性全删除。

    class Mymeta(type):
        def __call__(self, *args, **kwargs):
            obj = self.__new__(self)
            obj.__init__(*args, **kwargs)
            dic = {}
            dict.update(obj.__dict__)
            attr = {'attr':dic}
            obj.__dict__.clear()
            obj.__dict__.update(attr)
            
    
    class Test(dict,metaclass=Mymeta):
        def __init__(self,**kwargs):
            self.__dict__.update(kwargs)
        def __getattr__(self, item):
            return self.__dict__['attr'][item]
        def __setattr__(self, key, value):
            self.__dict__['attr'][key] = value
            t = Test(name='lqz', age=18)
    print(t.__dict__)
    print(t.name)
    print(t.age)
    t.male = 'nan'
    print(t.male)
    print(t.__dict__)
    

    五、有元类后属性查找顺序

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

    ​ 对象的属性查找顺序:先从对象自身找--->类中找--->mro继承关系去父类中找--->报错

    5f192fd059540a603a133d3ff0b0ca0

  • 相关阅读:
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(12月23日)
    北京Uber优步司机奖励政策(12月22日)
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(12月22日)
    北京Uber优步司机奖励政策(12月21日)
    PHP面向对象深入研究之【命名空间】与【自动加载类】
    PHP面向对象深入研究之【高级特性】
    PHP面向对象深入研究之【继承】,减少代码重复
    PHP实现物流查询(通过快递网API实现)
    PHP实现日志写入log.txt
    PHP 字符串 加*
  • 原文地址:https://www.cnblogs.com/tangceng/p/11455813.html
Copyright © 2020-2023  润新知