分享

一文掌握Python 最难知识点:元类

 excel05 2022-04-25
文章图片1

前言

在学习 python 过程中想必大家都会去看源码,看源码的过程中会看到一些元类,但是看起来感觉很吃力看不懂,那是因为我们对元类不够了解。

今天我们就来聊一聊 python 元类,看看元类到底是何方神圣。

2必要知识储备

在讲元类之前我们得先搞清楚类和对象的概念以及类的创建过程,这个至关重要,这取决于我们是否能真正理解和正确使用元类。

类和对象概念

1、类:用来描述具有相同的属性和方法的对象的集合(抽象)

2、对象:类的实体就是对象(具体)传统方式创建类

传统方式创建类

1、代码演示class Demo: def __init__(self,name): self.name = name print('初始化self.name = ',self.name)if __name__ == '__main__' print('Demo类是由谁创建的:',type(Demo)) print('Demo类的父类:',Demo.__bases__) cl = Demo('老王') print('cl实例是由谁创建的:',type(cl))2、输出:Demo类是由谁创建的:<class 'type'>Demo类的父类:(<class 'object'>,)初始化self.name = 老王cl实例是由谁创建的:<class '__main__.Demo'>3、结论:a、类(Demo)是由type创建的b、对象(cl)是由类(Demo)创建的c、基于类(Demo)创建对象(cl),先执行父类(object)的__new__()方法,返回对象(cl)

type 创建类

1、通过上面的例子我们知道,类是由type创建的,那么我们能不能直接通过type来创建类2、type语法type('类名',(继承哪个类,),{'属性名称':'属性值','方法名称key':'方法名称'})3、代码演示demo = type('Demo',(object,),{'name':'老王'})print('类名称:',demo.__name__)print('Demo类是由谁创建的:',type(demo))cl = demo()print('cl实例是由谁创建的:',type(cl))4、输出:类名称:DemoDemo类是由谁创建的:<class 'type'>cl实例是由谁创建的:<class '__main__.Demo'>5、结论a、类(Demo)是由type创建的b、对象(cl)是由类(Demo)创建的c、直接用type创建类和传统方式创建类,效果一模一样

3元类

概念

1、什么是元类:用来创建其他类的类叫元类
2、思考一个问题,我们能不能基于自己定义的类来创建其他的类?

自定义元类并创建类

1、代码演示class Demo1(type): def __init__(self,*args, **kwargs): super().__init__(*args, **kwargs)class Demo2(metaclass=Demo1): def __init__(self,name,age): self.name = name self.age = age print('Demo2类的实例属性:name={}'.format(self.name)) print('Demo2类的实例属性:age={}'.format(self.age))if __name__ == '__main__': print('Demo2是由谁创建的:',type(Demo2)) cl = Demo2('老王','20')2、输出:Demo2是由谁创建的:<class '__main__.Demo1'>Demo2类的实例属性:name=老王Demo2类的实例属性:age=203、结论a、类(Demo2)是由Demo1创建的b、可以通过自定义类来创建其他类

4元类经典应用

1、通过元类实现单例模式2、单例模式:在程序执行过程中一个类只实例化一次3、原理:干预类实例化的过程,如果已经实例化了就不再进行实例化class Demo1(type):    def __init__(self,name,bases, attrs):        super().__init__(name,bases, attrs)        self._instance = None    def __call__(self, *args, **kwargs):        #判断是否创建了对象,未创建就调用__new__()方法创建对象,已创建了就不调用__new__()方法,直接返回已创建好的对象        if self._instance is None:            self._instance = self.__new__(self,*args, **kwargs)        #调用自己类(Demo2)的实例化方法        self.__init__(self._instance,*args, **kwargs)        return self._instanceclass Demo2(metaclass=Demo1):    def __init__(self,name,age):        self.name = name        self.age = age        print('Demo2类的实例属性:name={}'.format(self.name))        print('Demo2类的实例属性:age={}'.format(self.age))if __name__ == '__main__':    print('Demo2是由谁创建的:',type(Demo2))    cl1 = Demo2('老王',20)    cl2 = Demo2('老王',20)    print('cl1实例的内存地址:',id(cl1))    print('cl2实例的内存地址:',id(cl1))    print('cl1 是否是 cl2',cl1 is cl2)4、输出:Demo2是由谁创建的:<class '__main__.Demo1'>Demo2类的实例属性:name=老王Demo2类的实例属性:age=20Demo2类的实例属性:name=老王Demo2类的实例属性:age=20cl1实例的内存地址:1842280993096cl2实例的内存地址:1842280993096cl1 是否是 cl2 True

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多