面向对象—的__new__()方法详解

[Python] Python 之 __new__() 方法与实例化

__new__() 是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在 Python 中存在于类里面的构造方法 __init__() 负责将类的实例化,而在 __init__() 启动之前,__new__() 决定是否要使用该 __init__() 方法,因为__new__() 可以调用其他类的构造方法或者直接返回别的对象来作为本类的实例。

 

如果将类比喻为工厂,那么__init__()方法则是该工厂的生产工人,__init__()方法接受的初始化参数则是生产所需原料,__init__()方法会按照方法中的语句负责将原料加工成实例以供工厂出货。而__new__()则是生产部经理,__new__()方法可以决定是否将原料提供给该生产部工人,同时它还决定着出货产品是否为该生产部的产品,因为这名经理可以借该工厂的名义向客户出售完全不是该工厂的产品。

 

__new__() 方法的特性:

  • __new__() 方法是在类准备将自身实例化时调用。
  • __new__() 方法始终都是类的静态方法,即使没有被加上静态方法装饰器。
  • 类的实例化和它的构造方法通常都是这个样子:
复制代码
class MyClass(object):def __init__(self, *args, **kwargs):...# 实例化
myclass = MyClass(*args, **kwargs)
复制代码

  

正如以上所示,一个类可以有多个位置参数和多个命名参数,而在实例化开始之后,在调用 __init__() 方法之前,Python 首先调用 __new__() 方法:

def __new__(cls, *args, **kwargs):...

  

第一个参数cls是当前正在实例化的类。

  • 如果要得到当前类的实例,应当在当前类中的 __new__() 方法语句中调用当前类的父类的 __new__() 方法。

  例如,如果当前类是直接继承自 object,那当前类的 __new__() 方法返回的对象应该为:

def __new__(cls, *args, **kwargs):...return object.__new__(cls)

  

注意:

  事实上如果(新式)类中没有重写__new__()方法,即在定义新式类时没有重新定义__new__()时,Python默认是调用该类的直接父类的__new__()方法来构造该类的实例,如果该类的父类也没有重写__new__(),那么将一直按此规矩追溯至object的__new__()方法,因为object是所有新式类的基类。

 

  而如果新式类中重写了__new__()方法,那么你可以自由选择任意一个的其他的新式类(必定要是新式类,只有新式类必定都有__new__(),因为所有新式类都是object的后代,而经典类则没有__new__()方法)的__new__()方法来制造实例,包括这个新式类的所有前代类和后代类,只要它们不会造成递归死循环。具体看以下代码解释:

 

复制代码
class Foo(object):def __init__(self, *args, **kwargs):...def __new__(cls, *args, **kwargs):return object.__new__(cls, *args, **kwargs)    

# 以上return等同于
# return object.__new__(Foo, *args, **kwargs)
# return Stranger.__new__(cls, *args, **kwargs)
# return Child.__new__(cls, *args, **kwargs)
class Child(Foo):def __new__(cls, *args, **kwargs):return object.__new__(cls, *args, **kwargs)
# 如果Child中没有定义__new__()方法,那么会自动调用其父类的__new__()方法来制造实例,即 Foo.__new__(cls, *args, **kwargs)。
# 在任何新式类的__new__()方法,不能调用自身的__new__()来制造实例,因为这会造成死循环。因此必须避免类似以下的写法:
# 在Foo中避免:return Foo.__new__(cls, *args, **kwargs)或return cls.__new__(cls, *args, **kwargs)。Child同理。
# 使用object或者没有血缘关系的新式类的__new__()是安全的,但是如果是在有继承关系的两个类之间,应避免互调造成死循环,例如:(Foo)return Child.__new__(cls), (Child)return Foo.__new__(cls)。
class Stranger(object):...
# 在制造Stranger实例时,会自动调用 object.__new__(cls)
复制代码

 

  •  通常来说,新式类开始实例化时,__new__()方法会返回cls(cls指代当前类)的实例,然后该类的__init__()方法作为构造方法会接收这个实例(即self)作为自己的第一个参数,然后依次传入__new__()方法中接收的位置参数和命名参数。

 

注意:如果__new__()没有返回cls(即当前类)的实例,那么当前类的__init__()方法是不会被调用的。如果__new__()返回其他类(新式类或经典类均可)的实例,那么只会调用被返回的那个类的构造方法。

复制代码
class Foo(object):def __init__(self, *args, **kwargs):...def __new__(cls, *args, **kwargs):return object.__new__(Stranger, *args, **kwargs)  class Stranger(object):...foo = Foo()
print type(foo)    

# 打印的结果显示foo其实是Stranger类的实例。

# 因此可以这么描述__new__()和__ini__()的区别,在新式类中__new__()才是真正的实例化方法,为类提供外壳制造出实例框架,然后调用该框架内的构造方法__init__()使其丰满。
# 如果以建房子做比喻,__new__()方法负责开发地皮,打下地基,并将原料存放在工地。而__init__()方法负责从工地取材料建造出地皮开发招标书中规定的大楼,__init__()负责大楼的细节设计,建造,装修使其可交付给客户。

转载于:https://www.cnblogs.com/TF511/p/10039159.html

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

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

相关文章

git使用回滚,清除暂缓区,解决冲突(持续更新)

1、git restore --staged <文件> 清除暂缓区文件名 2、git reset --hard <版本号> 回滚到上一版本 如看PHPstrom如何操作请参考https://blog.csdn.net/qq_35774849/article/details/107312658 3、解决冲突 &#xff08;1&#xff09;使用默认的解决冲突 打开…

14.安全

1.基本概念 安全问题的产生&#xff1a; 互联网作为商业交易的工具快速发展&#xff0c;越来越多的公司提供网络交易服务。很多商业活动在网上进行当前&#xff0c;成千上万的网民在网上进行各种活动的同时&#xff0c;也在网上传递其个人信息每天在网上发生各种各样的商业活动…

C语言enum关键字

很多初学者对枚举(enum)感到迷惑&#xff0c;或者认为没什么用&#xff0c;其实枚举(enum)是个很有用的数据类型。一、枚举类型的使用方法 一般的定义方式如下&#xff1a;enum enum_type_name{ENUM_CONST_1,ENUM_CONST_2,...ENUM_CONST_n} enum_variable_name;注意&#xff1a…

Dubbo 需求、架构、使用Demo

只是整理下方便自己记录 内容全部来自官网&#xff1a;http://dubbo.io/books/dubbo-user-book/preface/usage.html 一、需求 在大规模服务化之前&#xff0c;应用可能只是通过 RMI 或 Hessian 等工具&#xff0c;简单的暴露和引用远程服务&#xff0c;通过配置服务的URL地址进…

Ubuntu安装之python开发

Ubuntu安装之python开发 什么&#xff1f;&#xff1f;Ubuntu(乌班图)开发&#xff1f;不会用&#xff1f;&#xff1f;怎么进行python开发&#xff1f;&#xff1f;&#xff1f; 乌班图操作系统下载地址&#xff1a;http://releases.ubuntu.com/18.04/ubuntu-18.04.1-desktop-…

vimdiff和vim-fugitive安装,使用教程

1、vimdiff的安装 在终端执行 git config --global merge.tool vimdiff git config --global merge.conflictstyle diff3 git config --global mergetool.prompt false git config --global diff.tool vimdiff git config --global difftool.prompt false git config --…

在 PowerPoint 2016 中嵌入网页

之前在智图这个网站上做了一张地图&#xff0c;在嵌入 PPT 里面的时候碰到了一些问题&#xff0c;现在把找到的解决方法写下来。 PPT 里面自带的 WebBrowser 控件可以实现网页浏览的功能。在“开发工具”选项卡下的“其他控件”中找到“Microsoft Web Browser”&#xff0c;在画…

js 正则表达式 整合

正则表达式:断言 取字符串区间: /(?<[" star "]).*(?[" end "])/// 简单封装 Vue.prototype.strMatch (str,star,end) > { let regs new RegExp("(?<[" star "]).*(?[" end "])"); let req str…

dubbo 注册中心zookeeper 手册

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 zookeeper 注册中心 Zookeeper 是 Apacahe Hadoop 的子项目&#xff0c;是一个树型的目录服务&#xff0c;支持变更推送&#xff0c;适…

数组 深入详解

再论C语言数组 C语言处理数组的方式是它广受欢迎的原因之一。C语言对数组的处理是非常有效的&#xff0c;其原因有以下三点&#xff1a;第一&#xff0c;除少数翻译器出于谨慎会作一些繁琐的规定外&#xff0c;C语言的数组下标是在一个很低的层次上处理的。但这个优点也有一个反…

oracle ins-30131错误

打开cmd 但是在我的环境没效果&#xff0c;而我已知临时目录没有问题。那么在命令行进入安装软件目录&#xff0c;通过命令行启动安装程序&#xff0c;设置 ignorePrereq 检查&#xff0c;此时数据库软件可以启动安装&#xff0c;是否会出现错误&#xff0c;就看忽略的检查是否…

iOS开发UI篇—简单介绍静态单元格的使用

一、实现效果与说明 说明&#xff1a;观察上面的展示效果&#xff0c;可以发现整个界面是由一个tableview来展示的&#xff0c;上面的数据都是固定的&#xff0c;且几乎不会改变。 要完成上面的效果&#xff0c;有几种方法&#xff1a; &#xff08;1&#xff09;可以直接利用代…

展示内容

今天课上展示了软件 评价为过于简单 还需另寻他法转载于:https://www.cnblogs.com/wmqlzm/p/10041683.html

dubbo ,dubbo-provider、dubbo-consumer 配置参数说明

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 dubbo:consumer 服务消费者缺省值配置。配置类&#xff1a; com.alibaba.dubbo.config.ConsumerConfig 。同时该标签为 <dubbo:refer…

laraval使用sqlite设置从多少开始递增

DB::statement( "UPDATE SQLITE_SEQUENCE SET seq 起始值 WHERE name 表名" ); sqlite3默认就是1。 新建了含PRIMARY KEY AUTOINCREMENT 主键自增表(如 test1)后&#xff0c;会自动在sqlite_sequence表插入或更新一条信息&#xff0c;其中保存了相关主键的最大值&…

指针深入探讨

C语言变量的内存实质 一、先来理解C语言中变量的实质 要理解C指针&#xff0c;我认为一定要理解C中“变量”的存储实质&#xff0c;所以我就从“变量”这个东西开始讲起吧&#xff01;先来理解理解内存空间吧&#xff01;请看下图&#xff1a; 如上图所示&#xff0c;内存只不…

springboot_yml配置

server: port: 8097 session-timeout: 30 tomcat.max-threads: 0 tomcat.uri-encoding: UTF-8 spring: application: name: feedback # 数据库配置 datasource: name: test #url: jdbc:mysql://192.168.0.180:3306/dsdb #url: jdbc:m…

Python 字符串查找子串的方法之 index() 和 find()

find(substr, beg0, endlen(string)): 在[beg, end]范围内查找substring&#xff0c;找到返回substr的起始下标&#xff0c;否则返回 -1。 1 string Hello Python 2 print(string.find(h, 0, len(string))) # 输出 9 3 print(string.find(thon) # 输出 84 print(strin.find(…

sqlite 设置向下递增

因为 sqlite是没有floor函数的 所以用 cast(x as int) - (x < cast(x as int)) 原理 cast(1.1 as int) 1 cast(-1.1 as int) -1&#xff08;我们想要的结果为2&#xff09; 如果x为非负 cast(x as int)是可以的 但是有负的话就加上后面 (x < cast(x as int))…

Docker 是什么,组成

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 一、Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中&#xff0c;然后发布到任…