引言
前段时间刚好学习了,C++中类方面的内容,发现和Python中有许多不同之处,尤其是在类的继承这一块,今天有空,正好写篇文章,记录一下有兴趣的东西,也算是对Python的一个复习。
1 C++中的构造析构函数
介绍python前,先给大家看一下在C++中,对于构造,析构函数的写法
#include <iostream>
using namespace std;
//继承中的对象模型
class Base {
public:
Base()
{
cout << "Base的构造函数" << endl;
}
~Base()
{
cout << "Base的析构函数" << endl;
}
};
class Son : public Base {
public:
Son()
{
cout << "Son的构造函数" << endl;
}
~Son()
{
cout << "Son的析构函数" << endl;
}
};
void test01()
{
Son s;
// 继承中的构造和析构顺序如下:
// 构造:先构造父类,后子类
// 析构:和构造相反
}
int main()
{
test01();
return 0;
}
代码内容比较简单,就是一个Base类,一个Son类,子类继承父类内容,结果如下所示:可以看到在C++中的继承中,首先会调用父类的构造函数在调用子类的构造,在析构函数中,会先调用子类的析构函数,在调用父类的析构函数。那么问题来了,在Python中是怎么样的呢?
2 Python中的构造析构函数
2.1 仿照C++写法
class Base:
def __init__(self):
print("Base的构造函数")
def __del__(self):
print("Base的析构函数")
class Son(Base):
def __init__(self):
print("Son的构造函数")
def __del__(self):
print("Son的析构函数")
if __name__ == '__main__':
s = Son()
Python中的继承和C++不一样,在Python中,这样写的含义是对父类继承过来的方法进行了重写,那么如果我们想保留父类的内容,又添加子类的内容,应该这样写
2.2 继承父类方法一
我们一般情况下,都会使用内置的super()类,来继承父类中的内容,但是super在使用时,有一个注意点,因为程序是从上到下,依次执行的,super函数的位置不同,继承父类的时间也会不同
class Base:
def __init__(self):
print("Base的构造函数")
def __del__(self):
print("Base的析构函数")
class Son(Base):
def __init__(self):
super(Son, self).__init__()
print("Son的构造函数")
def __del__(self):
super(Son, self).__init__()
print("Son的析构函数")
if __name__ == '__main__':
s = Son()
结果如下:
分析:可以看到,调用的顺序依次是 父类构造,子类构造,父类析构,子类析构,是和C++中是不一样的,但是我们可以修改super调用的位置,达到和C++一样的效果
class Base:
def __init__(self):
print("Base的构造函数")
self.a = 20
def __del__(self):
print("Base的析构函数")
class Son(Base):
def __init__(self):
super(Son, self).__init__()
print("Son的构造函数")
def __del__(self):
print("Son的析构函数")
super(Son, self).__init__()
if __name__ == '__main__':
s = Son()
把子类中析构方法中的的super放在最下面,可以看到和C++一样
结论:由此可以推断出 ,在Python中,你只有写了super函数,才会调用父类的方法,否则,一切的操作都是对于类的重写,这边建议如果要继承并添加代码时,super写在最顶行, 以免出现错误。
案例
class Base:
def __init__(self):
print("Base的构造函数")
self.a = 20
def __del__(self):
print("Base的析构函数")
class Son(Base):
def __init__(self):
self.a = 10
super(Son, self).__init__()
print(self.a)
print("Son的构造函数")
def __del__(self):
print("Son的析构函数")
super(Son, self).__init__()
if __name__ == '__main__':
s = Son()
此时我们打印self.a的结果,大家可以试想一下结果。
其实这里我们想要的结果是10,但是由于继承了父类,在父类中,改变了自身的结果,导致出现了错误。
2.4继承父类方式二
在子类的方法中,直接调用父类的方法
class Base:
def __init__(self):
print("Base的构造函数")
def __del__(self):
print("Base的析构函数")
class Son(Base):
def __init__(self):
print("Son的构造函数")
Base.__init__(self)
def __del__(self):
print("Son的析构函数")
Base.__del__(self)
if __name__ == '__main__':
s = Son()
3Python中的多继承
class Base:
def __init__(self):
print("Base的构造函数")
def demo(self):
print("Base --- demo 方法")
class Base1:
def __init__(self):
print("Base1的构造函数")
def demo(self):
print("Base1 --- demo 方法")
class Son(Base,Base1):
def __init__(self):
print("Son的构造函数")
super(Son, self).__init__()
# Base.__init__(self)
def demo(self):
# super(Son, self).demo()
Base1.demo(self)
print("Son --- demo 方法")
if __name__ == '__main__':
s = Son()
print(Son.__mro__) # 利用Python中的 mro可以查看到类的调用顺序,从左到右执行,如果找到方法,就停止
s.demo()
利用super他会默认按照mro的顺序,去查找调用的顺序,如果我们不想按照这样的方式调用,可以直接用父类.demo(self)这样的方式进行继承,调用。