我们都知道一个最基本的魔术方法, __init__ 。通过此方法我们可以定义一个对象的初始操作。然而,当我调用 x = SomeClass() 的时候, __init__ 并不是第一个被调用的方法。

实际上,还有一个叫做 __new__ 的方法,来构造这个实例。然后给在开始创建时候的初始化函数来传递参数。

#__new__
__new__ 是在一个对象实例化的时候所调用的第一个方法。它的第一个参数是这个类,其他的参数是用来直接传递给__init__ 方法。

__new__ 方法相当不常用,但是它有自己的特性,特别是当继承一个不可变的类型比如一个tuple或者string。这里不再介绍__new__的更多细节,因为并不是很实用,python文档中有详细的阐述。

#__init__
此方法为类的初始化方法。当构造函数被调用的时候的任何参数都将会传给它。(比如如果我们调用 x = SomeClass(10, ‘foo’)),那么__init__ 将会得到两个参数10和foo。

__init__ 在Python的类定义中被广泛用到。

#区别

__new__:创建对象时调用,会返回当前对象的一个实例。

__init__:创建完对象后调用,对当前对象的一些实例初始化,无返回值。

1.在类中,如果__new__和__init__同时存在,会优先调用__new__

1
2
3
4
5
6
7
8
>>> class Data(object):
... def __new__(self):
... print "new"
... def __init__(self):
... print "init"
...
>>> data = Data()
new

2.__new__方法会返回所构造的对象,__init__则不会。__init__无返回值。

__new__:

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> class Data(object):
... def __new__(cls):
... print "new"
... cls.x = 1
... return cls
... def __init__(self):
... print "init"
...
>>> data = Data()
new
>>> data.x =1
>>> data.x
1

__init__:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Data(object):
... def __init__(cls):
... cls.x = 2
... print "init"
... return cls
...
>>> data = Data()
init
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() should return None, not 'Data'



>>> class Data(object):
... def __new__(cls):
... print "new"
... cls.x = 1
... return cls
... def __init__(self):
... print "init"
...
>>> data = Data()
new
>>> data.x =1
>>> data.x
1

3.如果__new__返回一个对象的实例,会隐式调用__init__,
如果__new__不返回一个对象的实例,__init__不会被调用。

__new__返回一个对象的实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
<class '__main__.B'>
>>> class A(object):
... def __new__(Class):
... object = super(A,Class).__new__(Class)
... print "in New"
... return object
... def __init__(self):
... print "in init"
...
>>> A()
in New
in init
<__main__.A object at 0x7fa8bc622d90>

__new__不返回一个对象的实例:

1
2
3
4
5
6
7
8
9
>>> class A(object):
... def __new__(cls):
... print "in New"
... return cls
... def __init__(self):
... print "in init"
...
>>> a = A()
in New

参考资料