對于使用過C++的人來說,構造函數(shù)與析構函數(shù)不會陌生。
構造函數(shù)在對象創(chuàng)建時被調用,析構函數(shù)在對象被銷毀時被調用。而Python中也有類似的特殊函數(shù):__new__,__init__,__del__。
其中__new__與__init__共同構成了C++中的構造函數(shù),__del__為析構函數(shù)。
__new__在對象被創(chuàng)建時被調用,而__init__在對象被初始化時被調用。
-
__new__的第一個參數(shù)是對象本身,其他的參數(shù)是用來直接傳遞給__init__方法。__new__方法相當不常用,但是當繼承一個不可變的類型(比如一個tuple或者string)時,它將派上用場。但這已經(jīng)超出了基礎的范圍,所以暫且不提。 -
__init__十分常見,用以初始化對象。當父類擁有該函數(shù),而繼承的子類想要調用父類的__init__,應該使用super().__init__()而不是父類名.__init__(),以此來避免多繼承問題。
__del__在對象被銷毀時被調用,但它并不是實現(xiàn)del語法的內(nèi)置函數(shù)。它定義的是對象被銷毀時的行為,但由于Python的GC問題,所以對象銷毀的時刻無法由編寫者完全自控,所以用處也較少。
附:多繼承問題
多繼承問題是一個古老的 Feature(當一個Bug沒法修的時候就叫 Feature)。讓我們運行如下代碼
class A():
def __init__(self):
print("進入A…")
print("離開A…")
class B(A):
def __init__(self):
print("進入B…")
A.__init__(self)
print("離開B…")
class C(A):
def __init__(self):
print("進入C…")
A.__init__(self
print("離開C…")
class D(B, C):
def __init__(self):
print("進入D…")
B.__init__(self)
C.__init__(self)
print("離開D…")
d = D()
結果如下
進入D…
進入B…
進入A…
離開A…
離開B…
進入C…
進入A…
離開A…
離開C…
離開D…
可以看到,A的__init__被調用了兩次。而這并不是我們期待的。為此在有些語言里,禁止了多繼承。
Python的解決方法是:使用super()調用父類方法。
class A():
def __init__(self):
print("進入A…")
print("離開A…")
class B(A):
def __init__(self):
print("進入B…")
super().__init__()
print("離開B…")
class C(A):
def __init__(self):
print("進入C…")
super().__init__()
print("離開C…")
class D(B, C):
def __init__(self):
print("進入D…")
super().__init__()
print("離開D…")
d = D()
運行結果如下
進入D…
進入B…
進入C…
進入A…
離開A…
離開C…
離開B…
離開D…
這樣A的__init__只被調用了一次