• 元类


    元类

    什么是元类?

    要知道什么是元类就必须要了解一个大前提:python中所有的都是对象

    在知道这个前提下我们就可以知道类也是一个对象 Σ(⊙▽⊙"a

    那么一个对象就会有一个类来负责创建它

    我们就把创建 “类”(实际也是一个对象)的 “类” 叫做——元类

    怎么找到元类呢?

    我们可以使用 type 方法来打印对象的类型

    那么我们是不是也可以用 type 来打印类的数据类型呢?

    print(type(list))   # <class 'type'>
    print(type(str))   # <class 'type'>
    print(type(object))   # <class 'type'>
    

    就连所有的类的基类都是object类都是由元类所创建的

    发现所有的类都是由 type 创建的。img

    ??type??这不是经常用的一个内置方法吗?

    怎么又变成了创建类的类了???

    虽然我们看不到它的源码,但是它很知趣的给了我们大概的解释:

    它可以传递一个参数或者传递三个参数:

    • 一个参数:对象的类型(来自百度翻译)
    • 三个参数:一个新对象(来自百度翻译)

    原来它真的就是可以用来创建对象。孤陋寡闻,孤陋寡闻。

    创建类的参数的含义

    • object_or_name :类名
    • bases : 继承的父类(元祖的形式传递)
    • dict :类的命名空间(所有的属性与方法)

    使用type创建一个类

    既然我们已经知道type怎么用了那么我们就用这个 “马良笔” 来手动的创建一个类

    def set_name(self,name):
        self.name = name
    
    def get_name(self):
        return self.name
    
    # 手动创建一个类
    Custom = type('Custom',(object,),{'set_name': set_name, 'get_name': get_name})
    # 实例化Custom类
    obj = Custom()
    obj.set_name('gredae')
    print(obj.get_name())   # gredae
    

    个人感觉class会不会也是重写了__enter__和__exit__方法来实现一个类的信息获取,再使用exce函数将类的名称空间里的所有属性与方法给写成一个字典,这样类的名称,类继承的所有父类,与类的属性与方法就全部都有了,再在底层调用type来生成类。。

    自定义一个元类

    type 好像是用C语言写的。嗯~算了,从入门到入坟。。。

    我们换一种思路吧!我们直接继承 type 然后对 type 的方法重写来实现自定义一个元类,嗯~可行性很高。

    class Mytype(type):
        pass
    Custom = type('Custom',(object,),{'set_name': set_name, 'get_name': get_name})
    print(type(Custom))   # <class '__main__.Mytype'>
    

    好了,我们实现了自定义元类,好像还没有重写它的方法。。

    重写方法之前要知道实例化一个类经过了那些步骤

    • 前面我们说到类也是对象,是由 type 创建的,那么我们将类实例化的时候是这样的 list() 当我们这样实例化类的时候就会调用 type__call__ 方法
    • 而后在 __call__ 方法里面先使用 __new__ 创建一个空白的对象,什么都没有的对象。
    • 然后使用新创建的这个对象来调用该类的 __init__ 来初始化这个对象
    • 最后再返回该对象。这样才能实例化一个类。

    虽然上面的步骤很多,但是实际实现起来也很多。嗯,没错。

    我们来实现自定义元类:

    class Mytype(type):
        def __call__(self, *args, **kwargs):
            obj = object.__new__(self)
            obj.__init__(*args, **kwargs)
            return obj
    
    class Custom(metaclass=Mytype):
        def set_name(self, name):
            self.name = name
    
        def get_name(self):
            return self.name
    
    f = Custom()
    print(type(f))   # <class '__main__.Custom'>
    print(type(Custom))   # <class '__main__.Mytype'>
    f.set_name('gredae')
    print(f.get_name())   # gredae
    

    终于一个功能齐全的自定义元类完成了。。

    属性查找

    最后再来说下类的属性查找和对象的属性查找

    • 类:先从类本身中找 -> mro继承关系去父类中找 -> 去自己定义的元类中找 -> type中 -> 报错
    • 对象:先从对象自身找 -> 类中找 -> mro继承关系去父类中找 -> 报错
  • 相关阅读:
    嵌入式Linux学习笔记 NAND Flash控制器
    (嵌入式开发)自己写bootloader之编写第一阶段
    C_C++指针指针应用详解
    数据结构笔记-----二叉排序树和哈希表
    map方法和filter方法
    nginx服务器卡住了 解决办法
    vue-devtoools 调试工具安装
    web 本地存储(localStorage、sessionStorage)
    vux使用教程
    一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了什么?
  • 原文地址:https://www.cnblogs.com/Gredae/p/11454220.html
Copyright © 2020-2023  润新知