構(gòu)造(__new__)和初始化(__init__)
透過上一篇的內(nèi)容,我們已經(jīng)知道定義一個(gè)類別時(shí),我們常常會(huì)透過 __init__(self) 的方法在實(shí)例化物件的時(shí)候,對(duì)屬性進(jìn)行設(shè)定。例如下面的例子:
#!/usr/bin/env python3 # -*- coding: UTF-8 -*- class User(object): def __init__(self, name, age): self.name = name; self.age = age; user=User('兩點(diǎn)水',23)
實(shí)際上,建立一個(gè)類別的過程是分成兩步驟的,一步是建立類別的對(duì)象,還有一步就是對(duì)類別進(jìn)行初始化。 __new__ 是用來建立類別並傳回這個(gè)類別的實(shí)例, 而__init__ 只是將傳入的參數(shù)來初始化該實(shí)例.__new__ 在建立一個(gè)實(shí)例的過程中必定會(huì)被呼叫,但__init__ 就不一定,例如透過pickle .load 的方式反序列化一個(gè)實(shí)例時(shí)就不會(huì)呼叫__init__ 方法。
def __new__(cls) 是在 def __init__(self) 方法之前呼叫的,作用是傳回一個(gè)實(shí)例物件。還有一點(diǎn)要注意的是:__new__ 方法總是需要傳回該類別的一個(gè)實(shí)例,而__init__ 不能傳回除了None 的任何值
具體的範(fàn)例:
#!/usr/bin/env python3 # -*- coding: UTF-8 -*- class User(object): def __new__(cls, *args, **kwargs): # 打印 __new__方法中的相關(guān)信息 print('調(diào)用了 def __new__ 方法') print(args) # 最后返回父類的方法 return super(User, cls).__new__(cls) def __init__(self, name, age): print('調(diào)用了 def __init__ 方法') self.name = name self.age = age if __name__ == '__main__': usr = User('兩點(diǎn)水', 23)
看看輸出的結(jié)果:
調(diào)用了 def __new__ 方法 ('兩點(diǎn)水', 23) 調(diào)用了 def __init__ 方法
透過列印的結(jié)果來看,我們就可以知道一個(gè)類別建立的過程是怎麼樣的了,先是呼叫了__new__ 方法來建立一個(gè)對(duì)象,把參數(shù)傳給__init__ 方法進(jìn)行實(shí)例化。
其實(shí)在實(shí)際開發(fā)中,很少會(huì)用到 __new__ 方法,除非你希望能夠控制類別的建立。通常講到 __new__ ,都是牽扯到 metaclass(元類)的。
當(dāng)然當(dāng)一個(gè)物件的生命週期結(jié)束的時(shí)候,析構(gòu)函數(shù) __del__ 方法會(huì)被呼叫。但是這個(gè)方法是 Python 自己對(duì)物件進(jìn)行垃圾回收的。