一文详解Python中__new__方法的作用

网站建设2年前 (2023)发布
33 0 0

Python中类的构造方法__new__方法有何作用?,Python类中有些方法名、属性名的前后都添加__双下画线,这种方法、属性通常属于Python的特殊方法和特殊属性。通过重写这些方法或直接调用这些方法来实现特殊功能。今天来聊聊构造方法__new__实际程序的应用场景。,我们知道常见的初始化__init__方法,可以重写实现自己想要的初始化逻辑。最近实际业务开发过程中碰到一类问题比如数据资源加载缓存机制的实现,用到了魔法方法中构造方法,其中__init__()和__new__是对象的构造器,合理运用将有效提高程序性能。,希望大家多结合自己的业务需求深刻理解,灵活运用,使得代码变得更加优雅。,接下来通过实例逐步详细阐述__ new __ 方法在类初始化过程中是什么样的存在!,注:,1)、代码实例化类过程,一般使用__init__()方法初始化一个类的实例,当代码中实例化一个类的时候,第一个调用执行的是__new__()方法,当定义的类中没有重新定义__new__()方法时候,Python会默认调用该父类的__new__()方法来构造该实例,new方法就是先创建一个空间,然后每次创建一个实例化的对象,然后用开辟的空间存放这个实例化对象; 再次创建一个实例化的对象的时候,再用new方法开辟一个空间存放实例化对象。注意只有继承了object的类才有此方法。,2)、内存地址和对象可相互转换,print(id(a))与 print(id(b))打印出来的都是内存地址(10进制),print(a)与 print(b)返回了类的名称和对象的地址,但是两者并不相同。每次实例化类都会创建分配不同的对象地址,因此,代码实例化类过程中返回类对象的地址引用也就不同。,注:,1)、__init__()方法和__new__()方法区别,__new__()方法用于创建实例,类实例化之前会首先调用,它是class的方法,是个静态方法。而__init__()方法用户初始化实例,该方法用在实例对象创建后被调用,它是实例对象的方法,用于设置类实例对象的一些初始值。,如果类中同时出现了__init__()方法和__new__()方法,则先调用__new__()方法后调用__init__()方法。__new__()方法是创建实例的第一步,执行完了需要返回创建的类的实例,否则则报错,无法执行__init__()方法。其中,__init__()方法将不返回任何信息。,2)、重写__new__()方法,super()与object.__new__(cls)都是在调用父类的new方法,必须把父类的new方法返回给函数,才能开辟空间,因此必须添加return。代码的执行顺序是:先执行new方法,然后执行init方法,最后是其它方法。,单例模式最初的定义出现于《设计模式》:“保证一个类仅有一个实例,并提供一个访问它的全局访问点。”,单例的使用主要是在需要保证全局只有一个实例可以被访问的情况,比如系统日志的输出、操作系统的任务管理器等。,注:,1)、单例模式始终只有一个空间,该空间一直重复利用。,首先定义一个类的私有属性_instance,用来记录第一个被创建对象的引用,如果cls._instance为None说明该类还没有实例化过,则实例化该类并返回实例对象。,通过以下数据测试可知,print(obj.name, obj.data)最后打印出来的都是A12,第一次打印”A11″时,属性为空,执行if语句开辟了一个空间存放该属性;从 第二次打已经开辟了空间 ,执行else语句,直接返回”A12″到原来的空间中,把前面的盖数据覆盖掉。,2)、单例模式另外一种实现方法,以上实现了单例模式对象空间的重复利用,但是有时候我们想初始化过程只加载一次,避免频繁请求浪费系统资源(如数据库连接请求数据)。,注:,1)、单例模式下仅加载一次初始化过程。,这时候我们在类空间中再添加一个init_flag属性来记录是否已经执行过初始化操作即可实现加载一次初始化过程。从以上两次实例化过程结果来看,对象引用地址不变,结果被最后一次实例化数据覆盖且初始化init只被打印一次。,2)、单例模式下一次资源加载注意点,单例模式下控制类仅进行一次初始化过程适用于资源一次性加载进缓存的过程,对于多进程应用可采用多例模式实现。,多个实例对象空间引用地址完全独立,从而保持避免不同请求资源不被占用。将同一个对象请求归为同一个实例。,注:,1)、多例模式始终具有多个空间,不同空间完全独立。,我们在类空间中定义类实例化对象字典,即建立不同的实例对象和对象空间地址引用键值对,从而实现多例模式。通过类字典判断实例对象是否创建,节省创建的成本。,2)、多例模式测试过程,当创建相同的实例对象name=”A11″时,程序首先在实例池中搜索cls._loaded.get(name),若存在则直接返回已创建的实例对象空间。多例模式完美的实现了不同访问对象具体不同的实例化对象地址。,3)、多例模式下缓冲机制的实现,进一步优化多例模式初始化过程,比如读取文件或者数据库时仅进行一次初始化加载。,注:多例模式下多个实例化对象均只进行一次初始化过程。,重写__new__方法中每个实例对象创建后绑定初始化_init_db()方法执行一次,后面遇到同一个实例对象将不会发生什么,直接返回已创建的实例对象。从测试结果来看,创建相同的实例对象name=”A11″时,第二次将略过初始化数据加载过程,很好的实现了缓存机制。,本文结合项目背景详细介绍了__new__方法实现单例模式和多例模式以及缓存机制的实现!,1、__new__ 方法是在类创建实例的时候自动调用的。,2、 实例是通过类里面的 __ new __ 方法是在类创建出来的。,3、 先调用__new__ 方法创建实例,再调用 __ init __方法初始化实例。,4、 __new__ 方法,后面的括号里面的cls代表的是类本身。,5、__new__ 方法,判断类属性为空就去开辟空间,否则复用原来的地址。,更多的特殊方法比如1、自我描述方法:__repr__2、析构方法:__del__ 3、列出对象所有属性(包括方法)名:__dir__4、__dict__属性:查看对象内部所有属性名和属性值组成的字典5、__getattr__\__setattr__等。,当然还有metaclass类的__new__方法,可以动态修改程序中的一批类,这个功能在开发一些基础性的框架时非常有用,可以使用metaclass为某一批需要通用功能的类添加方法,若有合适实例场景后续分享。

© 版权声明

相关文章