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__()负责大楼的细节设计,建造,装修使其可交付给客户。

python之__new__()的更多相关文章
- Python中__new__方法为什么有人说是构造方法?有什么作用?
__new__方法是Python新式类引入的,通常用于控制生成一个新实例的过程.它是类级别的静态方法,是在创建实例对象前执行,如果自定义类中没有重写该方法,则Python自动调用父类的方法,当所有父类 ...
- 第8.8节 Python使用__new__方法和构造方法__init__完成类实例化的过程详解
第8.8节 Python使用__new__方法和构造方法__init__完成类实例化的过程详解 前面章节介绍了Python类中的__new__方法和构造方法__init__,并通过实例分析了二者之间关 ...
- [Python] Python 之 __new__() 方法与实例化
__new__() 是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在 Python 中存在于类里面的构造方法 __init__() 负责将类的实例化,而在 __init__() ...
- 由Python通过__new__实现单例模式,所想到的__new__和__init__方法的区别
之前通过读书,了解到在Python中可以通过__new__方法来实现单例模式,代码一个示例如下,我就有了几个疑问,什么是单例模式?__new__方法是用来做什么的?用__new__方法实现的单例模式, ...
- Python 之 __new__() 方法与实例化
原文链接:https://www.cnblogs.com/ifantastic/p/3175735.html __new__() 是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解, ...
- Python之__new__方法
# -*- coding: utf-8 -*- """ Created on Sun Dec 2 11:03:03 2018 Python类构造过程 @author: z ...
- Python 之 __new__() 方法与实例化(转)
_new__() 是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在 Python 中存在于类里面的构造方法 __init__() 负责将类的实例化,而在 __init__() ...
- python的__new__方法
https://www.cnblogs.com/kex1n/p/5991249.html https://blog.csdn.net/wwx890208/article/details/8053445 ...
- Python中__new__的作用
__new__ 的作用 依照Python官方文档的说法,__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径.还 ...
随机推荐
- 【LDAP】LDAP注入漏洞与防御
0x01 前言 前两天爆了一个LDAP漏洞,据说存在了8年现在才被发现,感概一下,不知这8年来有多少站被搞了... 想着复现这个漏洞,就先复习一下LDAP注入的相关知识吧,差了很多资料,记一下笔记. ...
- python中矩阵的用法
python矩阵的表示真是让人头大,下面记录一下具体用法:array是numpy库里的.不管怎样, 一.首先导入 numpy: 1)import numpy 2)from numpy import * ...
- arcgis中的geodatabase模型
简介Geodatabase是ESRI公司定义的一个为ArcGIS所用的数据框架,该框架定义了ArcGIS中用到的所有的数据类型.不管ArcGIS的数据存储到何处.以什么格式存储,都脱离不了该框架.也可 ...
- pyqt5模块介绍
python各种库介绍 https://wiki.python.org/moin/GuiProgramming PyQt5.QtWidgets 包含控件 PyQt5.QtGui 图 ...
- Webstorm添加新建.vue文件功能并支持高亮vue语法和es6语法
转载:https://blog.csdn.net/qq_33008701/article/details/56486893 Webstorm 添加新建.vue文件功能并支持高亮vue语法和es6语法 ...
- 几个js框架
easyui适合做后端 bootstrap适合前端 layui 其实更偏向与后端开发人员使用,在服务端页面上有非常好的效果.
- luogu P4916 魔力环
传送门 表示这种\(Burnside\)定理之类的东西一用就忘qwq 题目要求不同染色方案数,因为变换方式只有旋转,所以只有\(n\)个置换,然后可能会出现某种方案有循环节,这个循环节长度显然要是\( ...
- 前端面试(二):N轮面试
一面 在一面中要掌握什么技巧,主要考察前端开发的基础知识 1.面试技巧.页面布局类 页面布局小结: 语义化掌握到位 页面布局理解深刻 CSS基础知识扎实 思维灵活且积极上进 代码书写规范 2.CSS盒 ...
- 第27月第18天 epoll lt et
1. While the usage of epoll when employed as a level-triggered interface does have the same semantic ...
- Spark思维导图之Spark Streaming