乍看一下上面两个方法功能相似,但其是其存在区别。
1 | __new__方法:用来构造一个类实例; |
那么从上面的差别来看,很明显需要首先调用new方法,构造实例后,才能够调用init初始化该实例。
两个方法的参数差异:
1 | __new__:方法用于构造实例,调用方法时传入的是类(CLS),而非实例(INSTANCE); |
相关知识:旧类与新类
在Python2中存在旧类与新类的概念,其中旧类指的是继承自type元类的类,而新类是继承自object类的类。
旧类代码:
1 | class oldStyleClass: # inherits from 'type' |
新类代码
1 | class newStyleClass(object): # explicitly inherits from 'object' |
在Python3中所有类默认继承自object,并不需要object作为基类;
我们现在就了解Python2中存在旧类与新类,他们只是继承的父类不同,那么也就继承了父类的方法与属性;相应的对new与init方法存在差异。
Python旧类中两方法的差异
- 旧类中没有new方法,其init方法起到了构造的作用;
- 旧类中init方法的返回值无法进行控制;
定义一个旧类:
1 | class oldStyleClass: |
可以看到即使,我们构造了一个new方法,在旧类的初始化过程中仍然不会调用它;
重载init方法时:
1 | class oldStyleClass: |
我们发现在函数的一开始就已经构造好了实例,并且返回了实例;
带返回值的init:
1 | class oldStyleClass: |
在旧类中无法控制,init的返回值。
Python新类中两方法差异
Python的新类允许用户重载__new__
和__init__
方法,且这两个方法具有不同的作用。__new__
作为构造器,起创建一个类实例的作用。而__init__
作为初始化器,起初始化一个已被创建的实例的作用。
1 | class newStyleClass(object): |
创建类实例并初始化的过程中__new__
和__init__
被调用的顺序也能从上面代码的输出结果中看出:__new__
函数首先被调用,构造了一个newStyleClass
的实例,接着__init__
函数在__new__
函数返回一个实例的时候被调用,并且这个实例作为self
参数被传入了__init__
函数。
这里需要注意的是,如果__new__
函数返回一个已经存在的实例(不论是哪个类的),__init__
不会被调用。如下面代码所示:
1 | obj = 12 |
同时另一个需要注意的点是:
如果我们在__new__
函数中不返回任何对象,则__init__
函数也不会被调用。
1 | class notReturnObj(object): |
可见如果__new__
函数不返回对象的话,不会有任何对象被创建,__init__
函数也不会被调用来初始化对象。
总结
__init__
不能有返回值__new__
函数直接上可以返回别的类的实例。如上面例子中的returnExistedObj
类的__new__
函数返回了一个int
值。- 只有在
__new__
返回一个新创建属于该类的实例时当前类的__init__
才会被调用。