最近在学到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__方法以及继承不可变类型类的问题的更多相关文章

  1. Python中的__new__()方法的使用

    __new__() 函数只能用于从object继承的新式类. 先看下object类中对__new__()方法的定义: class object:   @staticmethod # known cas ...

  2. Python中的__new__()方法与实例化

    @Python中的__new__()方法与实例化   __new__()是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在Python 中 存在于类里面的构造方法__init__ ...

  3. 第8.6节 Python类中的__new__方法深入剖析:调用父类__new__方法参数的困惑

    上节<第8.5节 Python类中的__new__方法和构造方法__init__关系深入剖析:执行顺序及参数关系案例详解>通过案例详细分析了两个方法的执行顺序,不知大家是否注意到了,在上述 ...

  4. JS中通过call方法实现继承

    原文:JS中通过call方法实现继承 讲解都写在注释里面了,有不对的地方请拍砖,谢谢! <html xmlns="http://www.w3.org/1999/xhtml"& ...

  5. python 中的__new__方法

    1.有关__new__方法的介绍 __new__方法调用在构造方法构造实例之前,即在__init__方法执行之前,我们可以这样理解,他的作用是决定是否适用这个__iint__方法来构造实例,但是需要注 ...

  6. 通俗的讲解Python中的__new__()方法

    2020-3-17更新本文,对本文中存争议的例子进行了更新! 曾经我幼稚的以为认识了python的__init__()方法就相当于认识了类构造器,结果,__new__()方法突然出现在我眼前,让我突然 ...

  7. 【转载】C#中Convert.ToDecimal方法将字符串转换为decimal类型

    在C#编程过程中,可以使用Convert.ToDecimal方法将字符串或者其他可转换为数字的对象变量转换为十进制decimal类型,Convert.ToDecimal方法有多个重载方法,最常使用的一 ...

  8. 【转载】C#中Convert.ToInt32方法将字符串转换为Int32类型

    在C#编程过程中,可以使用Convert.ToInt32方法将字符串或者其他可转换为数字的对象变量转换为ToInt32类型,Convert.ToInt32方法有多个重载方法,最常使用的一个方法将字符串 ...

  9. 【转载】C#中Convert.ToSingle方法将字符串转换为Float类型

    在C#编程过程中,可以使用Convert.ToSingle方法将字符串或者其他可转换为数字的对象变量转换为float类型,Convert.ToSingle方法有多个重载方法,最常使用的一个方法将字符串 ...

随机推荐

  1. androidBLE dfu升级使用及可能出现的问题

    android-dfu-library是nordic提供的对nRF5x芯片固件进行空中升级的库,地址是https://github.com/NordicSemiconductor/Android-DF ...

  2. Eclipse 代码快捷键模板(一)

    话不多说,自行google. 设置快捷键,打开eclipse,依次打开:Window -> Preferences -> General -> Key. 设置代码快捷键,打卡ecli ...

  3. HashMap、lru、散列表

    HashMap HashMap的数据结构:HashMap实际上是一个数组和链表("链表散列")的数据结构.底层就是一个数组结构,数组中的每一项又是一个链表. hashCode是一个 ...

  4. Kafka学习笔记(四)—— API使用

    Kafka学习笔记(四)-- API使用 1.Producer API 1.1 消息发送流程 Kafka的Producer发送消息采用的是异步发送的方式.在消息发送的过程中,涉及到了两个线程--mai ...

  5. Mysql 最全查询语句

    基本查询语句及语法: select distinct from where group by having limit 一.单表查询 前期表与数据准备: # 创建一张部门表 create table ...

  6. Java基础知识学习(一)--引用

    1.概念 如果一个变量的类型为类类型,而非基本类型,那么该变量就叫做引用:   2.对象引用 new Person(); 如上,代表创建了一个对象,但也仅仅是创建了,并没有办法去访问它.   为了访问 ...

  7. 使用Theia——添加语言支持

    上一篇:使用Theia——创建插件 Theia——添加语言支持 Theia中TextMate的支持 使用TextMate语法可以为大部分源文件提供精准的着色修饰,虽然这只是在语法级别上(没有语言本身的 ...

  8. spring cloud微服务快速教程之(四)熔断器(Hystrix)及其工具(Dashboard、Turbine)

    0-为什么需要熔断器 在分布式系统中,各个服务相互调用相互依赖,如果某个服务挂了,很可能导致其他调用它的一连串服务也挂掉或者在不断等待中耗尽服务器资源,这种现象称之为雪崩效应: 未来防止系统雪崩,熔断 ...

  9. Kubernetes 会不会“杀死” DevOps?

    作者丨孙健波(天元)  阿里巴巴技术专家 导读:DevOps 这个概念最早是在 2007 年提出的,那时云计算基础设施的概念也才刚刚提出没多久,而随着互联网的逐渐普及,应用软件的需求爆发式增长,软件开 ...

  10. 微信生成二维码 PHP

    <?php /** * Created by PhpStorm. * User: liyiming * Date: 2019/8/8 * Time: 14:23 */ # 生成二维码 class ...