zoukankan      html  css  js  c++  java
  • 类的高阶、元类、class底层实现原理

    一、元类

    ​ 在python中一切皆对象,类实际上也是一个对象。既然类是一个对象,那它一定有一个由一个类实例化得到,这个类,就叫做元类。也就是说产生类的类,叫元类。

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

    ​ 在python中可以通过type()方法查看对象的类

    print(type(dict))
    print(type(list))
    print(type(str))
    print(type(object))
    
    # 他们都是type
    

    二、class底层原理分析

    ​ type(object_or_name, bases, dict)----> 调用type()的__init__方法

    object_or_name: 类的名字,是个字符串

    bases:是它的所有父类,基类

    dict:名称空间,是一个字典

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

    # 通过type来直接产生类,不用class关键字了
    l = {}
    exex('''
    school = 'old_boy'
    def __init__(self, name):
    	self.name = name
    def score(self):
    	print('分数是100')
    ''', {}, l)  # 属性和方法、全局名称空间、局部名称空间
    
    Person = type('Person', (object,), l)
    
    print(Person.__dict__)
    print(Person.__bases__)
    p = Person('nick')
    print(p.name)
    print(p.__dict__)
    

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

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

    ​ 自定义元类必须继承type,写一个类继承type,这种类就叫元类

    练习一:加限制,控制类名必须以sb开头

    class Mymeta(type):
        def __init__(self, name, bases, dic):
            # 练习一:加限制 控制类名必须以sb开头
            if not name.startswith('sb'):
                raise Exception('类名必须以sb开头')
    
    # metaclass = Mymeta 指定这个类生成的时候,用自己写的Mymeta这个元类
    class Person(object, metaclass=Mymeta):
        school = 'old_boy'
        def __init__(self, name):
            self.name = name
        def score(self):
            print('分数是100')
    
    p = Person('nick')
    # 运行程序控制台报错:'类名必须以sb开头'
    

    练习二:类必须加注释

    class Mymeta(type):
        def __init__(self, name, bases, dic):
            # 练习二:类中必须要有类注释
            doc = self.__dict__['__doc__']
            if not doc:
                # 没有加注释
                raise Exception('你的类没有加注释')
               
    class Person(object, metaclass=Mymeta):
        """
        我是注释
        """
        school = 'oldboy'
        def __init__(self, name):
            self.name = name
           
    p = Person('nick')
    # 运行程序控制台不报错,因为类中有类注释
    

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

    ​ 控制类的调用过程,实际上就是控制对象的产生

    练习:将对象中所有的属性都变成私有的

    class Mymeta(type):
        def __call__(self, *args, **kwargs):
            # return self(*args) 会无限递归
            # 实例化产生一个Person类的对象,借助__new__来产生,需要把类传过去,才能产生对象
            obj = object.__new__(self)
            # 调用__init__方法完成初始化
            obj.__init__(*args, **kwargs)
            obj.__dict__ = {f'_{self.__name__}__{k}':v for k,v in obj.__dict__.items()}
            return obj
       
    class Person(object, metaclass=Mymeta):
        school = 'old_boy'
        def __init__(self, name):
            self.name = name
        def score(self):
            print('分数是100')
    
    P = Person(name='nick')
    print(p.__dict__)
    print(p.name)
    

    五、有了元类的属性查找

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

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

  • 相关阅读:
    python之mysqldb模块安装
    消失的那3个月__怎么看代码的小结
    四年测试经验总结
    python学习笔记系列----(八)python常用的标准库
    业务逻辑中的测试总结(二)----业务与数据库交互需求的测试分解
    python学习笔记系列----(七)类
    【QUESTION】
    python学习笔记系列----(六)错误和异常
    python学习笔记系列----(五)输入和输出
    Android6.0.1 移植:显示系统(一)--测试framebuffer
  • 原文地址:https://www.cnblogs.com/17vv/p/11453822.html
Copyright © 2011-2022 走看看