Python中的__new__()方法的使用

__new__() 函数只能用于从object继承的新式类。

 

先看下object类中对__new__()方法的定义:

class object:
  @staticmethod # known case of __new__
  def __new__(cls*more): # known special case of object.__new__
    """ T.__new__(S, ...) -> a new object with type S, a subtype of T """
    pass

object将__new__()方法定义为静态方法,并且至少需要传递一个参数cls,cls表示需要实例化的类,此参数在实例化时由Python解释器自动提供。

我们来看下下面类中对__new__()方法的实现:

class Demo(object):
  def __init__(self):
    print '__init__() called...'
  def __new__(cls*args, **kwargs):
    print '__new__() - {cls}'.format(cls=cls
    return object.__new__(cls*args, **kwargs)
if __name__ == '__main__':
  de = Demo()


输出:

发现实例化对象的时候,调用__init__()初始化之前,先调用了__new__()方法

__new__()必须要有返回值,返回实例化出来的实例,需要注意的是,可以return父类__new__()出来的实例,也可以直接将object的__new__()出来的实例返回。

__init__()有一个参数self,该self参数就是__new__()返回的实例,__init__()在__new__()的基础上可以完成一些其它初始化的动作,__init__()不需要返回值。

若__new__()没有正确返回当前类cls的实例,那__init__()将不会被调用,即使是父类的实例也不行。

我们可以将类比作制造商,__new__()方法就是前期的原材料购买环节,__init__()方法就是在有原材料的基础上,加工,初始化商品环节。

实际应用过程中,我们可以这么使用:

class LxmlDocument(object_ref):
  cache = weakref.WeakKeyDictionary()
  __slots__ = ['__weakref__']
  def __new__(cls, response, parser=etree.HTMLParser):
    cache = cls.cache.setdefault(response, {})
    if parser not in cache:
      obj = object_ref.__new__(cls)
      cache[parser] = _factory(response, parser)
    return cache[parser]

该类中的__new__()方法的使用,就是再进行初始化之前,检查缓存中是否存在该对象,如果存在则将缓存存放对象直接返回,如果不存在,则将对象放至缓存中,供下次使用。

 

再来个单例的,通过重载__new__实现单例:

class Singleton(object):def __new__(cls, *args, **kwargs):if not hasattr(cls, '_instance'):cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)return cls._instanc

一、__init__ 方法是什么?

使用Python写过面向对象的代码的同学,可能对 __init__ 方法已经非常熟悉了,__init__ 方法通常用在初始化一个类实例的时候。例如:

 

 

这样便是__init__最普通的用法了。但__init__其实不是实例化一个类的时候第一个被调用 的方法。当使用 Persion(name, age) 这样的表达式来实例化一个类时,最先被调用的方法 其实是 __new__ 方法。

二、__new__ 方法是什么?

__new__方法接受的参数虽然也是和__init__一样,但__init__是在类实例创建之后调用,而 __new__方法正是创建这个类实例的方法。

 

 

执行结果:

 

 

通过运行这段代码,我们可以看到,__new__方法的调用是发生在__init__之前的。其实当 你实例化一个类的时候,具体的执行逻辑是这样的:

1. p = Person(name, age)

2. 首先执行使用name和age参数来执行Person类的__new__方法,这个__new__方法会 返回Person类的一个实例(通常情况下是使用 super(Persion, cls).__new__(cls, ... ...) 这样的方式),

3. 然后利用这个实例来调用类的__init__方法,上一步里面__new__产生的实例也就是 __init__里面的的 self

所以,__init__ 和 __new__ 最主要的区别在于:

1.__init__ 通常用于初始化一个新实例,控制这个初始化的过程,比如添加一些属性, 做一些额外的操作,发生在类实例被创建完以后。它是实例级别的方法。

2.__new__ 通常用于控制生成一个新实例的过程。它是类级别的方法。

但是说了这么多,__new__最通常的用法是什么呢,我们什么时候需要__new__?

三、__new__ 的作用

依照Python官方文档的说法,__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。还有就是实现自定义的metaclass。

首先我们来看一下第一个功能,具体我们可以用int来作为一个例子:

假如我们需要一个永远都是正数的整数类型,通过集成int,我们可能会写出这样的代码。

 

 

但运行后会发现,结果根本不是我们想的那样,我们任然得到了-3。这是因为对于int这种 不可变的对象,我们只有重载它的__new__方法才能起到自定义的作用。

这是修改后的代码:

 

 

通过重载__new__方法,我们实现了需要的功能。

另外一个作用,关于自定义metaclass。其实我最早接触__new__的时候,就是因为需要自定义 metaclass,但鉴于篇幅原因,我们下次再来讲python中的metaclass和__new__的关系。

四、用__new__来实现单例

事实上,当我们理解了__new__方法后,我们还可以利用它来做一些其他有趣的事情,比如实现 设计模式中的 单例模式(singleton) 。

因为类每一次实例化后产生的过程都是通过__new__来控制的,所以通过重载__new__方法,我们 可以很简单的实现单例模式。

 

 

输出结果:

转载于:https://www.cnblogs.com/erhu/p/9567302.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/367532.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用Java分割大型XML文件

上周,我被要求用Java编写一些东西,该东西能够将单个30GB XML文件拆分为可配置文件大小的较小部分。 该文件的使用者将是一个中间件应用程序,该应用程序存在XML较大的问题。 在后台,它使用某种DOM解析技术,使它在一段时…

信号与线性系统翻转课堂笔记9——傅里叶变换概念

信号与线性系统翻转课堂笔记9——傅里叶变换 The Flipped Classroom9 of Signals and Linear Systems 对应教材:《信号与线性系统分析(第五版)》高等教育出版社,吴大正著 一、要点 (1,重点)…

from 下拉框多个值提交_Git commit 多行信息提交

git commit可接受多个消息标志(-m)来允许多行提交原文地址:https://www.stefanjudis.com/today-i-learned/git-commit-accepts-several-message-flags-m-to-allow-multiline-commits/原文作者:Stephan Schneider在命令行上使用git时,您可能已…

处理缓慢的资源泄漏

使用Java监视器查找资源泄漏 查找缓慢的资源泄漏是使应用程序服务器长时间保持正常运行的关键。 在这里,我解释了如何使用Java监视器来发现缓慢的资源泄漏,以及如何验证它们是实际的泄漏,而不仅仅是额外的预分配到某些HTTP连接器或数据库池中…

jquery简单实现点击弹出层效果实例

先看效果图&#xff1a;完整例子&#xff1a; <!-- 渐变弹出层 --><div id"race"><a href"#">点击</a></div><div id"racePop" class"raceShow">这里是弹出层效果</div> <script type&q…

Openfire源码阅读(一)

本篇先分析openfire源码的主要流程&#xff0c;模块细节后续再继续分析&#xff1b; 一、简介&#xff1a; Openfire是开源的实时协作服务器&#xff08;RTC&#xff09;&#xff0c;它是基于公开协议XMPP&#xff08;RFC-3920&#xff09;&#xff0c;并在此基础上实现了XMPP-…

php 查询方法all,获取多条:all静态方法

查询多条数据&#xff1a;all( )方法all方法与前节课学习的get方法都是静态方法&#xff0c;可用模型类直接访问2. 源码&#xff1a;/*** 查找所有记录* access public* param mixed $data 主键列表或者查询条件(闭包)* param array|string $with 关联预查询* param b…

[译文]过犹不及,别再在编程中高射炮打蚊子

原文链接&#xff1a;Anyway,stop recommending bazookas to kill flies in programming. 众成翻译地址&#xff1a;过犹不及&#xff0c;别再在编程中高射炮打蚊子 译者注&#xff1a;翻译这篇吐槽的文章&#xff0c;主要是为了自省~日常工作中确实会犯类似的错误&#xff0…

Java中的for循环

上一章呢我们学习了一下java中的while循环和do while循环 现在我们来了解一下另外一种循环 for循环 for循环是编程语言中一种开界的循环语句&#xff0c;而循环语句 由循环体及循环的终止条件两部分组成&#xff0c;for循环其在各种编程语言中的实现与表达有所出入&#xff0…

SpringFox swagger2 and SpringFox swagger2 UI 接口文档生成与查看

依赖&#xff1a; <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 --> <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version> <…

matlab期末复习资料,MATLAB期末复习习题及答案

MATLAB期末复习习题及答案13&#xff0c; ysin(x)&#xff0c;x从0到2 &#xff0c; x0.02 &#xff0c;求y的最大值、最小值、均值和标准差。(应用max,min,mean,std) 14&#xff0c; 参照课件中例题的方法&#xff0c;计算表达式z 10x3 y5e xcontour, hold on, quiver)15&…

多核可扩展计数器

到处都需要计数器&#xff0c;例如&#xff0c;查找应用程序的关键KPI&#xff0c;应用程序的负载&#xff0c;服务的请求总数&#xff0c;用于查找应用程序吞吐量的一些KPI等。 由于所有这些需求&#xff0c;并发复杂性也增加了&#xff0c;这使这个问题变得有趣。 如何实现…

三年前端,面试思考(二)

为什么还有&#xff08;二&#xff09; 没有想到上一篇 《三年前端&#xff0c;面试思考》 有这么多前端同学看到。 在评论区也有很多鼓励和质疑的声音&#xff0c;而且群里面交流的同学两天就达到了700人。 群里有同学问了很多问题&#xff0c;同时希望我再分享一些面试技巧…

51单片机auxr寄存器_MCS-51单片机有几个工作寄存器

工作寄存器有4组&#xff0c;每组都是8个工作寄存器R0~R7&#xff0c;通过PSW中的RS1、RS0两位来选择使用哪一组&#xff0c;如果不选&#xff0c;默认是选择第0组。RS1RS0组合为00时&#xff0c;选中第0组工作寄存器&#xff0c;R0~R7地址为00H~07H;RS1RS0组合为01时&#xff…

matlab中quat2angle,RPY_Euler_Quaternion_AngleAxis角度转化:Matlab、Python、Halc

RPY_Euler_Quaternion_AngleAxis角度转化&#xff1a;Matlab、Python、HalcRPY_Euler_Quaternion_AngleAxis角度转化&#xff1a;Matlab、Python、Halcon版本UR协作机器人和Franka机器人导出的位姿为angleVector&#xff0c;三个量表示&#xff0c;在Matlab中angleVector是四个…

基本注射/资格赛,范围

这是上周解决的DI / CDI基础知识的延续-在本文中&#xff0c;我将讨论基础注入&#xff0c;限定词和范围。 在上一个主题中&#xff0c;我们提供了有关DI / CDI概念的大量信息&#xff0c;我们还讨论了如何使用注释加载这些bean或类-这构成了对象的组成并创建了关于如何进行采…

100*100的 canvas 占多少内存?

题目 100*100的 canvas 占多少内存&#xff1f; 在 三年前端&#xff0c;面试思考 中提到了一个题目&#xff0c;非常有新意&#xff0c;这里分享一下当时面试的思考过程。 解题思路 其实真正的答案是多少我并不清楚&#xff0c;面试过程中面试官也不期待一个准确的答案&am…

1t硬盘怎么分区最好_这下尴尬了,电脑硬盘分区常见误区,移动硬盘分区方法...

大家买了新电脑硬盘要不要分区呢&#xff1f;像以往咱们买了新电脑一般会分4个区&#xff0c;C、D、E、F&#xff0c;方便更合理的分类使用&#xff0c;比如把工作放为D盘&#xff0c;娱乐影音放为E盘&#xff0c;游戏放为F盘&#xff0c;C盘为系统盘。不过渐渐地发现&#xff…

用Spring长轮询Tomcat

就像喜剧演员弗兰基 豪威尔 &#xff08; Frankie Howerd&#xff09;所说的“哦&#xff0c;小姐小姐” &#xff0c;但足够多的英国影射和双重诱惑&#xff0c;因为长轮询雄猫对隔壁的闷气不是某种性偏见&#xff0c;这是一种技术&#xff08;或更像是一种骇客&#xff09;由…

exchange 删除邮件

一 批量删除特定主题的邮件1.1 批量删除所有数据库中特定主题的邮件1) 群发了几封主题为“backup”的邮件&#xff1b; 2) 当前操作账号需要满足如下需求&#xff1a; a)该账号需属于Exchange Server 管理员角色以及源服务器和目标服务器的本地 Administrator组&#xff1b; b)…