最近在学到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. 复盘:错误理解zuul路径匹配,无法使用zuul

    场景: 项目中用到zuul时,配置url总是有问题,无法路由到对应微服务. 配置如下: zuul: routes: m2-member: path: /member/* serviceId: m2-m ...

  2. jQuery无new创建对象原理

    // jQuery 无new 创建对象套路 (function(g,undefined){ var foo = function(){ return new foo.fn.init(); }; foo ...

  3. 0001 认识WEB( 标准)

    认识WEB 1. 认识网页 网页主要由文字.图像和超链接等元素构成.当然,除了这些元素,网页中还可以包含音频.视频以及Flash等. 思考: 网页是如何形成的呢? 总结 网页有图片.链接.文字等元素组 ...

  4. alpha week 2/2 Scrum立会报告+燃尽图 06

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/9803 小组名称:“组长”组 组长:杨天宇 组员:魏新,罗杨美慧,王歆瑶, ...

  5. 深度探索c++对象模型阅读笔记图

  6. 【题解】NOIP2016 提高组 简要题解

    [题解]NOIP2016 提高组 简要题解 玩具迷题(送分) 用异或实现 //@winlere #include<iostream> #include<cstdio> #inc ...

  7. ECShop二次开发指南(一)

    ECSHOP是一套完整的网络商店解决方案,包括前台的商品展示.购物流程和强大易用的后台管理.由于 ecshop简单易用,使用者几乎可以在3几分钟简单的设置一下就可以拥有一个网上商店系统,所以很多的B2 ...

  8. Spark学习笔记(四)—— Yarn模式

    1.Yarn运行模式介绍 Yarn运行模式就是说Spark客户端直接连接Yarn,不需要额外构建Spark集群.如果Yarn是分布式部署的,那么Spark就跟随它形成了分布式部署的效果.有yarn-c ...

  9. Android/Unity大乱斗-完整双方集成交互指南

    这是一个很长很长的story!-芝麻粒儿创作 开篇 源码地址:GitHub 本文目的,将Unity集成到Android端,学完本文后你可以做到 Android任意布局加载Unity 3D场景 任意操作 ...

  10. java接入钉钉机器人(带源码)

    前言 登录钉钉网页: https://im.dingtalk.com 登录说明文档地址,以备随时查询: https://ding-doc.dingtalk.com/doc#/serverapi2/qf ...