Python中__new__和__init__的區別與聯絡

pythontab發表於2019-03-10

__new__ 和 __init__ 的區別主要表現在:

  1. 它自身的區別;

  2. 及在Python中新式類和老式類的定義

__new__ 負責物件的建立而 __init__ 負責物件的初始化。

__new__:建立物件時呼叫,會返回當前物件的一個例項

__init__:建立完物件後呼叫,對當前物件的一些例項初始化,無返回值

1. 在類中,如果__new__和__init__同時存在,會優先呼叫__new__

class ClsTest(object):
    def __init__(self):
        print("init")
    def __new__(cls,*args, **kwargs):
        print("new")
 
ClsTest()

輸出:

new

2. 如果__new__返回一個物件的例項,會隱式呼叫__init__

程式碼例項:

class ClsTest(object):
    def __init__(self):
        print ("init")
    def __new__(cls,*args, **kwargs):
        print ("new %s"%cls)
        return object.__new__(cls, *args, **kwargs)
 
ClsTest()

輸出:

new <class '__main__.ClsTest'>
init


3. __new__方法會返回所構造的物件,__init__則不會。__init__無返回值。

class ClsTest(object):
     def __init__(cls):
             cls.x = 2
             print ("init")
             return cls
 
ClsTest()

輸出:

init
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() should return None, not 'ClsTest'

4. 若__new__沒有正確返回當前類cls的例項,那__init__是不會被呼叫的,即使是父類的例項也不行

class ClsTest1(object):
    pass
 
class ClsTest2(ClsTest1):
    def __init__(self):
        print ("init")
    def __new__(cls,*args, **kwargs):
        print ("new %s"%cls)
        return object.__new__(ClsTest1, *args, **kwargs)
 
b=ClsTest2()
print (type(b))

輸出:

new <class '__main__.ClsTest2'>
<class '__main__.ClsTest1'>

知識點:

1. 繼承自object新式類才有__new__

2. __new__至少要有一個引數cls,代表要例項化的類,此引數在例項化時由Python直譯器自動提供,__new__必須要有返回值,返回例項化出來的例項,可以return父類__new__出來的例項,或者直接是object的__new__出來的例項

3. __init__有一個引數self,就是這個__new__返回的例項,__init__在__new__的基礎上可以完成一些其它初始化的動作,__init__不需要返回值

4. 如果__new__返回一個物件的例項,會隱式呼叫__init__


相關文章