iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Python中__new__方法有什么作用
  • 474
分享到

Python中__new__方法有什么作用

2023-07-06 02:07:19 474人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

本篇内容介绍了“python中__new__方法有什么作用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、__new__方法简介接下来通过

本篇内容介绍了“python中__new__方法有什么作用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

一、__new__方法简介

接下来通过实例逐步详细阐述__ new __ 方法在类初始化过程中是什么样的存在!

1、初始化数据加载+解析类实例
class Solution(object): def __init__(self, name=None,data=None): self.name = name self.data = data #初始化加载数据 self.xml_load(self.data) def xml_load(self,data): print("初始化init",data) def Parser(self): print("解析完成finish",self.name)a = Solution(name="A111",data=10)a.Parser()b = Solution(name="A112",data=20)b.Parser()# print(a)与 print(b)返回了类的名称和对象的地址print(a)print(b)# 可以使用内置函数id()查看Python对象的内存地址print(id(a))print(id(b))初始化init 10解析完成finish A111初始化init 20解析完成finish A11225178398098642517841042504

注:

1)、代码实例化类过程

一般使用__init__()方法初始化一个类的实例,当代码中实例化一个类的时候,第一个调用执行的是__new__()方法,当定义的类中没有重新定义__new__()方法时候,Python会默认调用该父类的__new__()方法来构造该实例,new方法就是先创建一个空间,然后每次创建一个实例化的对象,然后用开辟的空间存放这个实例化对象; 再次创建一个实例化的对象的时候,再用new方法开辟一个空间存放实例化对象。注意只有继承了object的类才有此方法。

2)、内存地址和对象可相互转换

#通过_ctypes的api进行对内存地址的对象import _ctypesobj = _ctypes.PyObj_FromPtr(id(a))#打印出来通过内存地址寻找到的对象print(obj)

print(id(a))与 print(id(b))打印出来的都是内存地址(10进制),print(a)与 print(b)返回了类的名称和对象的地址,但是两者并不相同。每次实例化类都会创建分配不同的对象地址,因此,代码实例化类过程中返回类对象的地址引用也就不同。

2、初始化数据加载重写new方法+解析类实例
class Solution: """ 注:new方法是为实例化对象创建空间的方法,现在new方法被改写,没有将实例化对象引用返回给python的解释器 无法为实例化对象创建空间存储,所以运行代码会报错。也没有完成初始化操作。 """ def __new__(cls, *args, **kwargs): print("对象创建空间") cls.instance = super().__new__(cls) print(cls.instance) # return cls.instance #若未返回实例对象引用,实例化方法将报错:AttributeError: 'NoneType' object has no attribute 'Parser' def __init__(self,name,data): self.name = name self.data = data self.xml_load(self.data) def xml_load(self,data): print("初始化init", data) def Parser(self): print("解析完成finish",self.data)a = Solution("A111",10)a.Parser()print(id(a))

注:

1)、__init__()方法和__new__()方法区别

__new__()方法用于创建实例,类实例化之前会首先调用,它是class的方法,是个静态方法。而__init__()方法用户初始化实例,该方法用在实例对象创建后被调用,它是实例对象的方法,用于设置类实例对象的一些初始值。

如果类中同时出现了__init__()方法和__new__()方法,则先调用__new__()方法后调用__init__()方法。__new__()方法是创建实例的第一步,执行完了需要返回创建的类的实例,否则则报错,无法执行__init__()方法。其中,__init__()方法将不返回任何信息。

2)、重写__new__()方法

def __new__(cls, *args, **kwargs): print(cls)# cls 代表的是Solution这个类本身cls.instance = super().__new__(cls)# object().__ new __() print(cls.instance) return cls.instance

super()与object.__new__(cls)都是在调用父类的new方法,必须把父类的new方法返回给函数,才能开辟空间,因此必须添加return。代码的执行顺序是:先执行new方法,然后执行init方法,最后是其它方法。

二、单例模式

单例模式最初的定义出现于《设计模式》:“保证一个类仅有一个实例,并提供一个访问它的全局访问点。”

单例的使用主要是在需要保证全局只有一个实例可以被访问的情况,比如系统日志的输出、操作系统的任务管理器等。

1、用new方法如何实现单例模式?
class Solution: # 1、记录第一个被创建对象的引用,代表着类的私有属性 _instance = None # 静态变量 存储在类的命名空间里的 def __init__(self,name,data): self.name = name self.data = data self.xml_load(self.data) def __new__(cls, *args, **kwargs): # 2.判断该类的属性是否为空;对第一个对象没有被创建,我们应该调用父类的方法,为第一个对象分配空间 if cls._instance == None: # 3.把类属性中保存的对象引用返回给python的解释器 cls._instance = object.__new__(cls)# 3 return cls._instance # 如果cls._instance不为None,直接返回已经实例化了的实例对象 else: return cls._instance# 必须把地址返回给new方法,让它有存储空间 def xml_load(self,data): print("初始化init",self.name,data) def Parser(self): print("解析完成finish",self.name)a = Solution("A11",10)#第一次开辟一个对象空间地址,后面创建都是在该地址上进行的a.Parser()b = Solution("A12",20)#b把a覆盖掉b.Parser()print(id(a))print(id(b))# 内存地址,而且它们的内存地址都是一样的print(a.name)print(b.name)
初始化init A11 10解析完成finish A11初始化init A12 10解析完成finish A1224651401998162465140199816A12A12

注:

1)、单例模式始终只有一个空间,该空间一直重复利用。

首先定义一个类的私有属性_instance,用来记录第一个被创建对象的引用,如果cls._instance为None说明该类还没有实例化过,则实例化该类并返回实例对象。

通过以下数据测试可知,print(obj.name, obj.data)最后打印出来的都是A12,第一次打印"A11"时,属性为空,执行if语句开辟了一个空间存放该属性;从 第二次打已经开辟了空间 ,执行else语句,直接返回"A12"到原来的空间中,把前面的盖数据覆盖掉。

def task(id,data): obj = Solution("{0}".fORMat(id), "{0}".format(data)) print(obj.name, obj.data)import threadingID=["A11","A12","A13","A14","A12"]DATA=[10,20,30,40,20]for i in range(5): t = threading.Thread(target=task(ID[i],DATA[i]), args=[i, ]) t.start()
初始化init A11 10A11 10初始化init A12 20A12 20初始化init A13 30A13 30初始化init A14 40A14 40初始化init A12 20A12 20

2)、单例模式另外一种实现方法

def __new__(cls,*args,**kwargs): # hasattr查询目标并判断有没有,not1==1返回的是False # if语句后面的 # not 条件整体为True时,执行cls.instance = object....代码 # if语句后面的 # not 条件整体为False时,执行return代码 if not hasattr(cls,"instance"): # hasattr查、判断的作用 cls.instance = object.__new__(cls) return cls.instance
2、如何控制类仅执行一次初始化方法?

以上实现了单例模式对象空间的重复利用,但是有时候我们想初始化过程只加载一次,避免频繁请求浪费系统资源(如数据库连接请求数据)。

class Solution: #定义类变量 # 记录第一个被创建对象的引用,代表着类的私有属性 _instance = None #记录是否执行过初始化动作 init_flag = False def __init__(self,name,data): self.name = name self.data = data #使用类名调用类变量,不能直接访问。 if Solution.init_flag: return self.xml_load(self.data) # 修改类属性的标记 Solution.init_flag = True def __new__(cls, *args, **kwargs): # 判断该类的属性是否为空;对第一个对象没有被创建,我们应该调用父类的方法,为第一个对象分配空间if cls._instance == None: # 把类属性中保存的对象引用返回给python的解释器 cls._instance = object.__new__(cls) return cls._instance #如果cls._instance不为None,直接返回已经实例化了的实例对象 else:return cls._instance def xml_load(self,data): print("初始化init",self.name,data) def Parser(self): print("解析完成finish",self.name)a = Solution("A11",10)#第一次实例化对象地址,后面创建都是在该地址上进行的a.Parser()b = Solution("A12",20)#b把a覆盖掉b.Parser()print(id(a))print(id(b))print(a.name)print(b.name)
初始化init A11 10解析完成finish A11解析完成finish A1222808557203282280855720328A12A12

注:

1)、单例模式下仅加载一次初始化过程。

这时候我们在类空间中再添加一个init_flag属性来记录是否已经执行过初始化操作即可实现加载一次初始化过程。从以上两次实例化过程结果来看,对象引用地址不变,结果被最后一次实例化数据覆盖且初始化init只被打印一次。

2)、单例模式下一次资源加载注意点

单例模式下控制类仅进行一次初始化过程适用于资源一次性加载进缓存的过程,对于多进程应用可采用多例模式实现。

三、多例模式

多个实例对象空间引用地址完全独立,从而保持避免不同请求资源不被占用。将同一个对象请求归为同一个实例。

class Solution: ##定义类实例化对象字典,即不同的实例对象对应不同的对象空间地址引用 _loaded = {} def __init__(self,name,data): self.name = name self.data = data self.xml_load(self.data) def __new__(cls, name,*args): if cls._loaded.get(name) is not None: client = cls._loaded.get(name) print(f"已经存在访问对象 {name}") print(client) return client # 把类属性中保存的对象引用返回给python的解释器 print(f"正在创建访问对象 {name}") client = super().__new__(cls) # 为该类实例name添加一个空间对象地址引用 print(client) cls._loaded[name] = client return client def xml_load(self,data): print("初始化init",self.name,data) def Parser(self): print("解析完成finish",self.name)if __name__ == '__main__': print("多例模式实例") a = Solution("A11",10) a.Parser() b = Solution("A11",10) b.Parser() c = Solution("A12", 20) c.Parser() print(f"{a is b}") print(a.name) print(b.name) print(c.name)

注:

1)、多例模式始终具有多个空间,不同空间完全独立。

我们在类空间中定义类实例化对象字典,即建立不同的实例对象和对象空间地址引用键值对,从而实现多例模式。通过类字典判断实例对象是否创建,节省创建的成本。

2)、多例模式测试过程

当创建相同的实例对象name="A11"时,程序首先在实例池中搜索cls._loaded.get(name),若存在则直接返回已创建的实例对象空间。多例模式完美的实现了不同访问对象具体不同的实例化对象地址。

多例模式实例正在创建访问对象 A11初始化init A11 10解析完成finish A11已经存在访问对象 A11初始化init A11 10解析完成finish A11正在创建访问对象 A12初始化init A12 20解析完成finish A12TrueA11A11A12

3)、多例模式下缓冲机制的实现

进一步优化多例模式初始化过程,比如读取文件或者数据库时仅进行一次初始化加载。

class Solution: ##定义类实例化对象字典,即不同的实例对象对应不同的对象空间地址引用 _loaded = {} def __new__(cls, name,data,*args): if cls._loaded.get(name) is not None: client = cls._loaded.get(name) print(f"已经存在访问对象 {name}") print(client) return client print(f"正在创建访问对象 {name}") # 把类属性中保存的对象引用返回给python的解释器 client = super().__new__(cls) print(client) # 为该类实例name添加一个空间对象地址引用 cls._loaded[name] = client client._init_db(name,data) return client def _init_db(self,name,data): self.name = name self.data = data self.xml_load(self.data) def xml_load(self,data): print("初始化init",self.name,data) def Parser(self): print("解析完成finish",self.name)if __name__ == '__main__': print("多例模式实例-缓存") a = Solution("A11",10) a.Parser() b = Solution("A11",10) b.Parser() c = Solution("A12", 20) c.Parser() print(f"{a is b}") print(a.name) print(b.name) print(c.name)
多例模式实例正在创建访问对象 A11初始化init A11 10解析完成finish A11已经存在访问对象 A11解析完成finish A11正在创建访问对象 A12初始化init A12 20解析完成finish A12TrueA11A11A12

注:多例模式下多个实例化对象均只进行一次初始化过程。

重写__new__方法中每个实例对象创建后绑定初始化_init_db()方法执行一次,后面遇到同一个实例对象将不会发生什么,直接返回已创建的实例对象。从测试结果来看,创建相同的实例对象name="A11"时,第二次将略过初始化数据加载过程,很好的实现了缓存机制。

“Python中__new__方法有什么作用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: Python中__new__方法有什么作用

本文链接: https://www.lsjlt.com/news/357384.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Python中__new__方法有什么作用
    本篇内容介绍了“Python中__new__方法有什么作用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、__new__方法简介接下来通过...
    99+
    2023-07-06
  • Python中__new__方法有什么用
    这篇文章主要为大家展示了“Python中__new__方法有什么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Python中__new__方法有什么用”这篇文章吧。一、__new__方法简介接...
    99+
    2023-06-29
  • Python 中__new__方法的作用是什么
    今天就跟大家聊聊有关Python 中__new__方法的作用是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。__new__ 的作用在Python中__new__方法与__init...
    99+
    2023-06-02
  • Python中__init__和__new__方法有什么用
    这篇文章给大家分享的是有关Python中__init__和__new__方法有什么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。__ init __方法init方法负责对象的初始化,系统执行该方法前,其实该对象...
    99+
    2023-06-02
  • 详解Python中__new__方法的作用
    目录前言一、__new__方法简介1、初始化数据加载+解析类实例2、初始化数据加载重写new方法+解析类实例二、单例模式1、用new方法如何实现单例模式2、如何控制类仅执行一次初始化...
    99+
    2024-04-02
  • 一文详解Python中__new__方法的作用
    前言Python中类的构造方法__new__方法有何作用?Python类中有些方法名、属性名的前后都添加__双下画线,这种方法、属性通常属于Python的特殊方法和特殊属性。通过重写这些方法或直接调用这些方法来实现特殊功能。今天来聊聊构造方...
    99+
    2023-05-14
    Python __new__
  • python中__init__ 和__new__有什么区别
    python中__init__ 和__new__有什么区别?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。python的五大特点是什么python的五大特点:1....
    99+
    2023-06-15
  • Python中Pandas方法有什么作用
    本篇内容介绍了“Python中Pandas方法有什么作用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!pandas.cut(x, bins,...
    99+
    2023-06-02
  • Python中class内置方法__init__与__new__作用与区别解析
    目录背景__init__方法作用__new__方法作用__init__ && __new__联系使用__new__的场景定义、继承immutable class使用m...
    99+
    2024-04-02
  • Python 中类的构造方法 __New__的妙用
    目录1、概述 2、__new__ 和 __init__ 的区别3、应用1:改变内置的不可变类型4、应用2:实现一个单例5、应用3:客户端缓存6、应用4:不同文件不同的解密方法1、概述...
    99+
    2024-04-02
  • Python的__Init__ 和__New__有什么区别
    这篇文章主要讲解了“Python的__Init__ 和__New__有什么区别”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python的__Init__ 和__New__有什么区别”吧!简...
    99+
    2023-07-06
  • 怎么使用HTML5__init__、__new__、__call__方法
    这篇文章主要讲解了“怎么使用HTML5__init__、__new__、__call__方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用HTML5__init__、__new__、...
    99+
    2023-06-01
  • jquery中hover方法有什么作用
    这篇文章主要讲解了“jquery中hover方法有什么作用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“jquery中hover方法有什么作用”吧! ...
    99+
    2024-04-02
  • javascript中stop方法有什么作用
    这篇文章主要介绍“javascript中stop方法有什么作用”,在日常操作中,相信很多人在javascript中stop方法有什么作用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大...
    99+
    2024-04-02
  • java中tostring方法有什么作用
    Java中的toString方法用于返回对象的字符串表示形式。它通常被用于打印对象的值或调试目的。具体来说,当一个对象被传递给Sys...
    99+
    2023-08-31
    java tostring
  • python中map()方法有什么用
    小编给大家分享一下python中map()方法有什么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!map()方法:map() 会根据提供的函数对指定序列做映射。...
    99+
    2023-06-17
  • python中append()方法有什么用
    在Python中,append()方法用于在列表的末尾追加一个新的元素。通过调用该方法,可以将一个新的元素添加到列表最后,从而扩展列...
    99+
    2024-03-06
    python
  • python中getattribute方法有什么用
    这篇文章主要介绍了python中getattribute方法有什么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Python的优点有哪些1、简单易用,与C/C++、Java...
    99+
    2023-06-14
  • python中filter()方法有什么用
    这篇文章主要为大家展示了“python中filter()方法有什么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“python中filter()方法有什么用”这篇文章吧。filter()方法(过...
    99+
    2023-06-17
  • python中reduce()方法有什么用
    这篇文章主要为大家展示了“python中reduce()方法有什么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“python中reduce()方法有什么用”这篇文章吧。reduce()方法:r...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作