• python元类(type)


    下面是一段python基于类创建对象的代码

    1. class Foo(object):
    2. def __init__(self, name):
    3. self.name = name;
    4. obj=Foo('LYJ')

    基于这个类创建对象一般会分为两部走:

    1. 程序自动帮你调用new方法、创建对象(空对象)-----构造方法

    2. 程序接着执行类中的init方法,初始化该空对象 -----初始化方法

    所以:对象是基于类创建出来的

    那么类是由谁创建的呢?先说结论:

    类默认是由type创建的

    为什么这么说呢,下面看两段代码:

    在我们日常写代码的过程中,传统创建方式是:

    1. class Foo(object):
    2. val = 1
    3. def func(self):
    4. return "Hello World!"

    除了这种,其实还有一种不常见的创建方法:

    Foo = type('Foo', (object),{'val':1,"func":lambda self:888})

    上面这两种创建方法其实都是由type创建,只不过第一种更为直观而已;

    类默认是由type创建的,那该怎么让一个类的创建改成由别的东西来创建呢?此时就有了元类

    1. class MyType(type):
    2. pass
    3. class Foo(object, metaclass=MyType):
    4. pass

    此时Foo就是由mytype创建的类,那么当Foo被创建的时候,就会调用mytype里面的方法(类似于mytype类创建出了一个Foo对象)

    将这段代码再详细展开和剖析一下:

    1. class MyType(type):
    2. def __new__(cls, *args, **kwargs):
    3. # 为当前的Foo创建了一个空类
    4. new_cls = super().__new__(cls, *args, **kwargs)
    5. return new_cls
    6. def __init__(cls, *args, **kwargs):
    7. # 初始化该类
    8. super().__init__(cls, *args, **kwargs)
    9. def __call__(self, *args, **kwargs):
    10. # 调用本类的__new__方法去创建对象
    11. empty_obj = self.__new__(self)
    12. # 调用本类中的__init__方法初始化Foo类
    13. self.__init__(empty_obj, *args, **kwargs)
    14. return empty_obj
    15. class Foo(object, metaclass=MyType):
    16. def __init__(self, name):
    17. self.name = name
    18. def __call__(self, *args, **kwargs):
    19. print('foo_call')
    20. # 类的实例化
    21. # Foo()会优先执行mytype中的call方法
    22. v = Foo('lyj')
    23. # 此时会执行Foo的call方法
    24. v()

    这里的__call__方法和python面向对象里面的__call__方法相同,具体可以参看我的另一篇文章:

    http://t.csdnimg.cn/8nZiw

    下面我们再捋一边上面这个代码:

    1. 首先定义了一个MyType元类,该元类继承了type类,并且在MyType内部定义了三个方法,new方法帮我们创建空类,init方法用于初始化该空类,call方法使得该类的实例可以像函数一样被调用
    2. 接着定义了一个Foo类,该类基于MyType创建,此时Foo类已经创建,可以正常使用
    3. 接着我们通过Foo('lyj')会优先调用MyType中的call方法,该call方法又会调用MyType中的new和init方法创建类,该类会接着实例化一个对象

  • 相关阅读:
    静态代码块和代码块的执行顺序解说
    Redis缓存序列化配置
    短视频矩阵系统seo源码saas开发---一手源头
    IP地址c++题解
    python的opencv操作记录(十)——图像融合
    【Leetcode】旋转系列(数组、矩阵、链表、函数、字符串)
    云原生(二十八) | Kubernetes篇之自建高可用k8s集群搭建
    hadoop2.2.0开机启动的后台服务脚本(请结合上一篇学习)
    飞致云开源社区月度动态报告(2023年9月)
    一文概括AxureRP的优缺点和替代软件
  • 原文地址:https://blog.csdn.net/m0_74033027/article/details/136640949