对于使用过C++的人来说,构造函数与析构函数不会陌生。
构造函数在对象创建时被调用,析构函数在对象被销毁时被调用。而Python中也有类似的特殊函数:__new__
,__init__
,__del__
。
其中__new__
与__init__
共同构成了C++中的构造函数,__del__
为析构函数。
__new__
在对象被创建时被调用,而__init__
在对象被初始化时被调用。
-
__new__
的第一个参数是对象本身,其他的参数是用来直接传递给__init__
方法。__new__
方法相当不常用,但是当继承一个不可变的类型(比如一个tuple或者string)时,它将派上用场。但这已经超出了基础的范围,所以暂且不提。 -
__init__
十分常见,用以初始化对象。当父类拥有该函数,而继承的子类想要调用父类的__init__
,应该使用super().__init__()
而不是父类名.__init__()
,以此来避免多继承问题。
__del__
在对象被销毁时被调用,但它并不是实现del
语法的内置函数。它定义的是对象被销毁时的行为,但由于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__
只被调用了一次