Python3中的__new__方法以及继承不可变类型类的问题
最近在学到Python中的__new__方法时被弄懵逼了,一开始实在是很难理解,有很多地方想不通(本人强迫症)。最近自己慢慢思索得出了能说服自己的理解:
说__new__方法之前要先提到__init__方法,__init__方法是普遍认为的Python类的构造方法,在我们对类进行实例化的时候,Python解释器会调用__init__方法对我们在init方法中定义的属性进行初始化,比如:
class demo():
def __init__(self,arg,kwarg): #定义属性并初始化
self.arg = arg
self.kwarg = kwarg
def Output(self):
print(self.arg)
print(self.kwarg) a = demo("NMSL","WSND") #实例化
a.Output() #调用类中的Output方法
但是其实在Python中,__init__并不是真正的构造函数,准确的说,__new__加__init__才是真正的构造函数,下面详细说一下__new__方法。
当我们在对类进行实例化的时候,Python解释器会从__new__方法的返回值中获取到实例对象的信息,在上面代码的例子中,我们把类demo进行实例化,对象为a
在这个过程中,类demo是怎么确定它的实例对象是a呢,就是__new__方法返回了这个值,这个值就是a,然后Python解释器就知道了demo这个类的对象为a,其实这里的返回值最后被Python解释器告诉__init__方法,init方法中的关键字self其实就是这个a,因为self代表的是类的对象。
__new__方法还有另一个用处就是用来实现单例设计模式以及继承不可变类的时候方便我们定制类:
class newfloat(float):
def __new__(cls,value):
return super().__new__(cls,round(value,4))
i = newfloat(3.14529)
print(i)
这里的思路是用来接收__new__方法的返回值再打印出来。
老实说我在很多文章下面看到过关于__new__方法的应用,都是拿这个举例子,但是我觉得根本没有必要这样,我觉得可以这样:
class demo(int):
def __init__(self,arg):
self.arg = arg
self.arg = round(self.arg,4)
print(self.arg)
a = demo(3.1415926)
这样的写法同样能实现功能。
单例设计模式是为了解决一个类有多个对象的时候,多个对象引用同一个内存地址,以减少内存占用的问题。
实现思路:
重写父类的__new__方法,使每次返回的内存地址引用都为同一个。
class demo(object):
ins = None
def __new__(cls): if cls.ins == None:
cls.ins = super().__new__(cls)
return cls.ins
a = demo()
b = demo()
print(a)
print(b)
这里的思路是:定义一个类属性ins为空值,再在重写__new__方法时候用if语句进行判断,如果ins为空则赋给它__new__方法的返回值,当用a去实例化demo时,
实际上是Python解释器为这次实例化开辟了一片内存空间,a就是引用了这个内存地址。
然后我们再用b去实例化demo,由于ins的值已经被改写,所以返回的是同样的之前a对象的内存地址,这样就成功实现了单例设计模式。
这里必须好好解释一下__new__方法的参数,在定义new方法时,在参数栏里不能写self,而是写cls,self代表的是类的实例,而cls则代表的是类本身。
继承不可变类型,我们知道Python中的不可变类型有int,str和tuple,但是Python中有这么一个思想:万物皆对象。也就是说,int,str和tuple这中数据类型其实也是一种对象,拿字符串举例,我们可以利用count之类的方法直接对字符串进行操作,但是这其实是Python内置类str中定义的方法,我们可以用dir()方法查看类中定义有哪些方法,但是在重写new方法时最多只能多传一个参数,这是为什么?
下面时我自己的解释,我们平时用内置方法比如count()时,一次只能对一个字符串进行操作,理所应当,每次当我们重写str类中定义的方法时,只能传入一个值。
其他注意事项:
__init__方法不能有返回值,而__new__方法却必须有返回值。
如有错误,请指正,感激不尽。
Python3中的__new__方法以及继承不可变类型类的问题的更多相关文章
- Python中的__new__()方法的使用
__new__() 函数只能用于从object继承的新式类. 先看下object类中对__new__()方法的定义: class object: @staticmethod # known cas ...
- Python中的__new__()方法与实例化
@Python中的__new__()方法与实例化 __new__()是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在Python 中 存在于类里面的构造方法__init__ ...
- 第8.6节 Python类中的__new__方法深入剖析:调用父类__new__方法参数的困惑
上节<第8.5节 Python类中的__new__方法和构造方法__init__关系深入剖析:执行顺序及参数关系案例详解>通过案例详细分析了两个方法的执行顺序,不知大家是否注意到了,在上述 ...
- JS中通过call方法实现继承
原文:JS中通过call方法实现继承 讲解都写在注释里面了,有不对的地方请拍砖,谢谢! <html xmlns="http://www.w3.org/1999/xhtml"& ...
- python 中的__new__方法
1.有关__new__方法的介绍 __new__方法调用在构造方法构造实例之前,即在__init__方法执行之前,我们可以这样理解,他的作用是决定是否适用这个__iint__方法来构造实例,但是需要注 ...
- 通俗的讲解Python中的__new__()方法
2020-3-17更新本文,对本文中存争议的例子进行了更新! 曾经我幼稚的以为认识了python的__init__()方法就相当于认识了类构造器,结果,__new__()方法突然出现在我眼前,让我突然 ...
- 【转载】C#中Convert.ToDecimal方法将字符串转换为decimal类型
在C#编程过程中,可以使用Convert.ToDecimal方法将字符串或者其他可转换为数字的对象变量转换为十进制decimal类型,Convert.ToDecimal方法有多个重载方法,最常使用的一 ...
- 【转载】C#中Convert.ToInt32方法将字符串转换为Int32类型
在C#编程过程中,可以使用Convert.ToInt32方法将字符串或者其他可转换为数字的对象变量转换为ToInt32类型,Convert.ToInt32方法有多个重载方法,最常使用的一个方法将字符串 ...
- 【转载】C#中Convert.ToSingle方法将字符串转换为Float类型
在C#编程过程中,可以使用Convert.ToSingle方法将字符串或者其他可转换为数字的对象变量转换为float类型,Convert.ToSingle方法有多个重载方法,最常使用的一个方法将字符串 ...
随机推荐
- 中文javadoc
大量的中文注释,其实最大的目的是想生成中文的Javadoc.但是中文注释实在太不高级了,在各种编码下还会变成乱码.本着高端大气国际化的思路,还是想把它换成英文,但是又不想放弃中文的Javadoc,怎么 ...
- 小心Powershell的位数
我们都知道64位的 Windows 中有两个Powershell,32位的 Windows Powershell(x86)和64位的 Windows Powershell.(当然,32位的Window ...
- CUP计算资源争抢通过IIS启用处理器关联解决
由于业务的复杂性,我们在客户环境部署的时候,采用的是预装好在一台机器然后再把机器安装到客户环境,所以为了简单方便,我们把所有的服务都安装到一台机器上面了. 在正常的使用过程中是没有任何问题的.但是当有 ...
- Vue.js provide / inject 踩坑
最近学习JavaScript,并且使用vuejs,第一次使用依赖注入,结果踩坑,差点把屏幕摔了..始终获取不到如组件的属性,provide中的this对象始终是子组件的this对象 慢慢也摸索到了些v ...
- lnmp一键安装,安装php时失败
查看安装日志 直接cd进入根目录报错内容:configure: error: mcrypt.h not found. Please reinstall libmcrypt 解决办法如下#使用wget可 ...
- hadoop常用端口及定义方法
hadoop2.x常用到的组件:HDFS, YARN, HBase, Hive, ZooKeeper: 组件 节点 默认端口 配置 用途说明HDFS DataNode 50010 dfs.datano ...
- 35.python之事件驱动模型
转载:https://www.cnblogs.com/yuanchenqi/articles/5722574.html 事件驱动模型 上节的问题: 协程:遇到IO操作就切换. 但什么时候切回去呢?怎么 ...
- Java中的选择结构
1.if选择结构 if选择结构是根据条件判断之后再做处理的一种语法结构 语法: if(条件){ 代码块 //条件成立之后要执行的代码,可以是一条语句,也可以是一组语句 } if后小括号里的条件是一个表 ...
- UVW平台运动控制算法以及matlab仿真
UVW平台运动控制算法以及matlab仿真 最近公司同事因为对某视觉对位平台的运动控制算法有疑问,所以来请教我.由于我也是第一次接触到UVW自动对位平台(也可以叫XXY自动对位平台),于是找了一些 ...
- jquery中为动态增加的元素添加事件
// html代码 <ul id="main"> </ul> // js代码 $(function(){ // 动态添加html代码 $("#ma ...