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继承关系去父类中找--->报错

  • 相关阅读:
    解释机器学习模型的一些方法(一)——数据可视化
    机器学习模型解释工具-Lime
    Hive SQL 语法学习与实践
    LeetCode 198. 打家劫舍(House Robber)LeetCode 213. 打家劫舍 II(House Robber II)
    LeetCode 148. 排序链表(Sort List)
    LeetCode 18. 四数之和(4Sum)
    LeetCode 12. 整数转罗马数字(Integer to Roman)
    LeetCode 31. 下一个排列(Next Permutation)
    LeetCode 168. Excel表列名称(Excel Sheet Column Title)
    论FPGA建模,与面向对象编程的相似性
  • 原文地址:https://www.cnblogs.com/17vv/p/11453822.html
Copyright © 2011-2022 走看看