python中_new_()与_init_()的区别
__new__方法的使用
只有继承于object的新式类才能有__new__方法,__new__方法在创建类实例对象时由Python解释器自动调用,一般不用自己定义,Python默认调用该类的直接父类的__new__方法来构造该类的实例,如果该类的父类也没有重写__new__,那么将一直按此规矩追溯至object的__new__方法,因为object是所有新式类的基类,若需要自定义__new__方法,一般用法如下:
class Person(object):
def __new__(cls):
return object.__new__(cls)
__new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供;__new__必须要有返回值,返回实例化出来的实例,可以return父类new出来的实例,或直接是object的new出来的实例。
object.new(cls)执行完返回的结果为Person类的实例对象,如下:
class Person(object):
def __init__(self):
print("__init__")
self.name="张三"
def __new__(cls):
print('__new__')
ob = object.__new__(cls)#ob为Person实例对象
print(ob)
return ob
p1 = Person()
print(p1.name)

p1=Person()该语句主要做了以下工作:
首先调用Person的__new__方法,该方法通过object.new(cls)创建了Person实例对象,并返回。最后调用了该Person实例对象的__init__方法。
object.new()方法接收的参数是类对象,可以不是当前类对象cls,如果将cls换成其他类对象会发生什么呢,看下面代码的运行结果:
class Dog(object):
def __init__(self):
self.name="旺财"
print("Dog.__init__")
class Person(object):
def __init__(self):
self.name="张三"
print("Person.__init__")
def __new__(cls):
print('__new__')
ob = object.__new__(Dog)
return ob
p1 = Person()
print(type(p1))

由结果得知p1是Dog类的实例,但是有个问题,Python解释器没有自动执行__init__方法,由结果可以看出并没有打印字符串__init__。若__new__()没有正确返回当前类cls的实例,那__init__()将不会被调用。 我们可以在__new__方法中手动调用__init__方法(实际开发中好像没什么用)
class Dog(object):
def __init__(self):
self.name="旺财"
print("__init__") class Person(object):
def __init__(self):
self.name="张三"
print("__init__")
def __new__(cls):
print('__new__')
ob = object.__new__(Dog)
ob.__init__()
return ob p1 = Person()
print(type(p1))
print(p1.name)

使用魔术方法__new__计算在创建实例的时候调用累加方法
如下场景:
假设我有一个学生类和一个班级类,想要实现的功能为:
执行班级人数增加的操作、获得班级的总人数;
学生类继承自班级类,每实例化一个学生,班级人数都能增加;
最后,我想定义一些学生,获得班级中的总人数。
思考:这个问题用类方法做比较合适,为什么?因为我实例化的是学生,但是如果我从学生这一个实例中获得班级总人数,在逻辑上显然是不合理的。同时,如果想要获得班级总人数,如果生成一个班级的实例也是没有必要的。
class ClassTest(object):
__num = 0 @classmethod
def addNum(cls):
cls.__num += 1 @classmethod
def getNum(cls):
return cls.__num # 这里我用到魔术方法__new__,主要是为了在创建实例的时候调用累加方法。
def __new__(self):
ClassTest.addNum()
return super(ClassTest, self).__new__(self) class Student(ClassTest):
def __init__(self):
self.name = '' a = Student()
b = Student()
print(ClassTest.getNum())
_new_()与_init_()的区别

可见,当类中同时出现__new__()和__init__()时,先调用__new__(),再调用__init__(),具体的执行过程为:
1. 调用实例对象代码xiaoming = Student('xiaoming',175);
2. 传入name和height的参数,执行Student类的__new__()方法,该方法返回一个类的实例,通常会用父类super(Student,cls).__new__(cls),__new__()产生的实例即__init__()的self;
3. 用实例来调用__init__()方法,进行初始化实例对象的操作。
可以看到,python中__new__()与__init__()的区别,
1.首先用法不同,__new__()用于创建实例,所以该方法是在实例创建之前被调用,它是类级别的方法,是个静态方法;
而 __init__() 用于初始化实例,所以该方法是在实例对象创建后被调用,它是实例级别的方法,用于设置对象属性的一些初始值。
由此可知,__new__()在__init__() 之前被调用。如果__new__() 创建的是当前类的实例,会自动调用__init__()函数,通过return调用的__new__()的参数cls来保证是当前类实例,如果是其他类的类名,那么创建返回的是其他类实例,就不会调用当前类的__init__()函数。
2.其次传入参数不同
__new__()至少有一个参数cls,代表当前类,此参数在实例化时由Python解释器自动识别;
__init__()至少有一个参数self,就是这个__new__()返回的实例,__init__()在__new__()的基础上完成一些初始化的操作。
3.返回值不同
__new__()必须有返回值,返回实例对象;
__init__()不需要返回值。
另外谈谈__new__()的作用,__new__()方法主要用于继承一些不可变的class,比如int, str, tuple, 提供一个自定义这些类的实例化过程的途径,一般通过重载__new__()方法来实现。代码如下

另外__new__()方法还可以用来实现单例模式,也就是使每次实例化时只返回同一个实例对象。

https://www.cnblogs.com/jayliu/p/9013155.html
https://blog.csdn.net/weixin_41557802/article/details/84190218
python中_new_()与_init_()的区别的更多相关文章
- Python中type与Object的区别
Python中type与Object的区别 在查看了Python的API后,总算明白了.现在总结如下: 先来看object的说明: Python中关于object的说明很少,甚至只有一句话: clas ...
- Python中生成器和迭代器的区别(代码在Python3.5下测试):
https://blog.csdn.net/u014745194/article/details/70176117 Python中生成器和迭代器的区别(代码在Python3.5下测试):Num01–& ...
- Python中的is和==的区别,==判断值是否相等,is判断地址是否一致
Python中的is和==的区别 Python中的对象包含三要素:id.type.value. 其中id用来唯一标示一个对象,type标识对象的类型,value是对象的值. is判断的是a对象是否就是 ...
- _new_()与_init_()的区别
先上代码 其中,__new__()不是一定要有,只有继承自object的类才有,该方法可以return父类(通过super(当前类名, cls).__new__())出来的实例,或者直接是obje ...
- 基于python中staticmethod和classmethod的区别(详解)
例子 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 class A(object): def foo(self,x): print "executing foo ...
- Python中send()和sendall()的区别
Python中send()和sendall()的区别 估计每个学习Python网络编程的人,都会遇到过这样的问题: send()和sendall()到底有什么区别? send()和sendall()原 ...
- Python中的is和==的区别
Python中的is和==的区别 1. is 是比较内存地址id() a = "YongJie" b = "YongJie" print(id(a)) #233 ...
- python中break和continue的区别
python中break和continue的区别 break和continue 1.break 意思为结束循环 例: i = 0 while i<10: i+=1 if ...
- 从python中copy与deepcopy的区别看python引用
讨论copy与deepcopy的区别这个问题要先搞清楚python中的引用.python的内存管理. python中的一切事物皆为对象,并且规定参数的传递都是对象的引用.可能这样说听起来比较难懂,对比 ...
随机推荐
- HashMap原理探究
一.写随笔的原因:HashMap我们在平时都会用,一般面试题也都会问,借此篇文章分析下HashMap(基于JDK1.8)的源码. 二.具体的内容: 1.简介: HashMap在基于数组+链表来实现的, ...
- Linux系统文件系统及文件基础篇
学习Linux,重难点在于掌握不同类别的文件系统及其作用.通过对Linux系统的安装,我们首先来了解下Linux系统里各个目录文件夹下的大致功能:主要的目录树的有/./root./home./usr. ...
- python-装饰(高阶函数)
python-装饰(高阶函数) 高阶函数 1.把一个函数名当做实参传给另外一个函数(在不修改被装饰函数源代码) 2.返回值 中包含函数名 高阶函数实现1的功能 def bar(): print(&qu ...
- cgicc使用
CgiCc 使用 一.下载 下载地址: http://ftp.gnu.org/gnu/cgicc/ ftp://ftp.gnu.org/gnu/cgicc/ 二.配置.编译.安装 下载完成后解压:sh ...
- 架构师成长之路5.1-Saltstack安装及入门
点击架构师成长之路 架构师成长之路5.1-Saltstack安装及入门 (安装.配置.启动) 配置管理工具: Pupper:1. 采用ruby编程语言:2. 安装环境相对较复杂:3.不支持远程执行,需 ...
- fiddler4自动生成jmeter脚本
接口.性能测试任务当遇到从浏览器或移动app自己抓包的情况出现时就变得巨苦逼了,苦在哪里?苦在需要通过抓包工具抓报文,需要通过抓包报文梳理业务逻辑.需要将梳理的逻辑编写成脚本.最最苦的情况是,自己抓包 ...
- mysql之InnoDb引擎与MyISAM引擎对比
InnoDb引擎 支持ACID的事务,支持事务的四种隔离级别: 支持行级锁及外键约束:因此可以支持写并发: 不存储总行数: 一个InnoDb引擎存储在一个文件空间(共享表空间,表大小不受操作系统控制, ...
- css 点击打开遮罩
<div> <nav class="bar bar-tab"> <a class="tab-item external" href ...
- 如何制作chrome浏览器插件之一
方法如下: 1.创建一个单独的文件夹,比如说为百度贴吧开发一个插件,就叫TiebaAddion.之后在这个文件夹里创建一个名字为"manifest.json"的文件,在里面写上如下 ...
- 微信小程序data数组push和remove问题
因为在做一个小程序的demo时.由于不向后台请求数据,所以就涉及到对本地数据的操作,现在就做一些数组的增删 //添加新元素 addItemFn: function () { var { lists } ...