Python语言中的__new__和__init__的区别
小标 2018-12-10 来源 : 阅读 1054 评论 0

摘要:本文主要向大家介绍了Python语言中的__new__和__init__的区别,通过具体的内容向大家展示,希望对大家学习Python语言有所帮助。

本文主要向大家介绍了Python语言中的__new__和__init__的区别,通过具体的内容向大家展示,希望对大家学习Python语言有所帮助。

讨论了Python中__init__和__new__方法。

__new__和__init__具有不同的功能。并且对于Python的新类和旧类而言功能也不同。

__new__和__init__功能上的区别

__new__和__init__的主要区别在于:__new__是用来创造一个类的实例的(constructor),而__init__是用来初始化一个实例的(initializer)。

Python的新类和旧类

Python中的类分为新类和旧类。旧类是Python3之前的类,旧类并不是默认继承object类,而是继承type类。

Python2中的旧类如下面代码所示:

class oldStyleClass: # inherits from 'type'
   pass

Python2中定义一个新类:

class newStyleClass(object): # explicitly inherits from 'object'
   pass

在Python3中所有的类均默认继承object,所以并不需要显式地指定object为基类。

以object为基类可以使得所定义的类具有新类所对应的方法(methods)和属性(properties)。

在下面的文章中我们会分别基于新类和旧类探讨__new__和__init__。

__new__和__init__参数的不同

__new__所接收的第一个参数是cls,而__init__所接收的第一个参数是self。这是因为当我们调用__new__的时候,该类的实例还并不存在(也就是self所引用的对象还不存在),所以需要接收一个类作为参数,从而产生一个实例。而当我们调用__init__的时候,实例已经存在,因此__init__接受self作为第一个参数并对该实例进行必要的初始化操作。这也意味着__init__是在__new__之后被调用的。

Python旧类中的__new__和__init__

Python的旧类中实际上并没有__new__方法。因为旧类中的__init__实际上起构造器的作用。所以如果我们定义如下旧类:

class oldStyleClass:
   def __new__(cls):
       print("__new__ is called") # this line will never get called during constructionoldStyleClass()

程序输出结果如下:

<__main__.oldStyleClass instance at 0x109c45518>

可见创建及初始化对象的过程并没有调用__new__。实际上,除非显式调用:oldStyleClass.__new__(oldStyleClass),该类中的__new__方法中的内容永远不会被调用。因为旧类构造实例并不会调用__new__方法。

但如果我们重载__init__方法:

class oldStyleClass:
   def __init__(self):
       print("__init__ is called")

oldStyleClass()

该程序将会输出

__init__ is called
<__main__.oldStyleClass instance at 0x1091992d8>

如果我们在__init__中加上return语句,将会导致TypeError: __init__() should return None的错误。

class oldStyleClass:
   def __init__(self):        return 29oldStyleClass()

程序结果如下:

TypeError: __init__() should return None

这意味着对于Python的旧类而言,我们无法控制__init__函数的返回值。

Python新类中的__new__和__init__

Python的新类允许用户重载__new__和__init__方法,且这两个方法具有不同的作用。__new__作为构造器,起创建一个类实例的作用。而__init__作为初始化器,起初始化一个已被创建的实例的作用。

如下面代码是所示:

class newStyleClass(object):
   # In Python2, we need to specify the object as the base.
   # In Python3 it's default.

   def __new__(cls):
       print("__new__ is called")        return super(newStyleClass, cls).__new__(cls)    def __init__(self):
       print("__init__ is called")
       print("self is: ", self)

newStyleClass()

结果如下:

__new__ is called
__init__ is called
self is: <__main__.newStyleClass at 0x109290890>
<__main__.newStyleClass at 0x109290890>

创建类实例并初始化的过程中__new__和__init__被调用的顺序也能从上面代码的输出结果中看出:__new__函数首先被调用,构造了一个newStyleClass的实例,接着__init__函数在__new__函数返回一个实例的时候被调用,并且这个实例作为self参数被传入了__init__函数。

这里需要注意的是,如果__new__函数返回一个已经存在的实例(不论是哪个类的),__init__不会被调用。如下面代码所示:

obj = 12 # obj can be an object from any class, even object.__new__(object)class returnExistedObj(object):
   def __new__(cls):
       print("__new__ is called")        return obj    def __init(self):
       print("__init__ is called")

returnExistedObj()

执行结果如下:

__new__ is called12

同时另一个需要注意的点是:

如果我们在__new__函数中不返回任何对象,则__init__函数也不会被调用。

如下面代码所示:

class notReturnObj(object):
   def __new__(cls):
       print("__new__ is called")    def __init__(self):
       print("__init__ is called")

print(notReturnObj())

执行结果如下:

__new__ is calledNone

可见如果__new__函数不返回对象的话,不会有任何对象被创建,__init__函数也不会被调用来初始化对象。

总结几个点

__init__不能有返回值

__new__函数直接上可以返回别的类的实例。如上面例子中的returnExistedObj类的__new__函数返回了一个int值。

只有在__new__返回一个新创建属于该类的实例时当前类的__init__才会被调用。如下面例子所示:

class sample(object):
   def __str__(self):
       print("sample")class example(object):
   def __new__(cls):
       print("__new__ is called")        return sample()    def __init__(self):
       print("__init__ is called")

example()

输出结果为:

__new__ is called
sample

本文由职坐标整理并发布,希望对同学们学习Python有所帮助,更多内容请关注职坐标编程语言Python频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程