本系列文章配套代码获取有以下三种途径:
-
可以在以下网站查看,该网站是使用JupyterLite搭建的web端Jupyter环境,因此无需在本地安装运行环境即可使用,首次运行浏览器需要下载一些配置文件(大约20M):
https://returu.github.io/Python_Basic/lab/index.html
-
也可以通过百度网盘获取,需要在本地配置代码运行环境,环境配置可以查看【Python基础】2.搭建Python开发环境:
链接:https://pan.baidu.com/s/1x2Ynh_VibPY2u-HWTaJo8w?pwd=mnsj
提取码:mnsj
-
前往GitHub详情页面,单击 code 按钮,选择Download ZIP选项:
https://github.com/returu/Python_Basic
——————————————————
在Python中类与类之间存在派生或继承的关系,这种关系针对的是父类、子类的关系而言:父类可以派生子类,与此同时,子类也继承了父类的属性和方法;子类也可以定义属于自己的属性和方法。通过这种父类子类的关系设计程序结构,就是典型的面向对象编程思想。
继承就是根据现有类创建新类,同时根据需要做做一些改动,是重用代码的好办法。当你使用继承时,新类会自动使用旧类的所有代码,无须自己动手复制任何内容。
1.单继承:
单继承的实现,只需要定义新类时,在类名后面加上圆括号,圆括号里面指定父类的类名即可。
1class DerivedClassName(FatherClassName)
原始类被称为父类、超类或基类,新类被称为子类、次类或派生类。
1# 定义一个类
2>>> class Vehicle:
3... Chinese_translation = "交通工具"
4...
5... def __init__(self , category):
6... self.category = category
7...
8... def get_info(self):
9... return f"交通工具类别为:{self.category}。"
10
11# 从父类继承
12>>> class Car(Vehicle):
13... pass
14
15>>> a_car = Car("小汽车")
16>>> a_car.get_info()
17'交通工具类别为:小汽车。'
18>>> a_car.Chinese_translation
19'交通工具'
从上面的示例可以看到,新类最初会继承父类的一切。
既然定义了一个新类,肯定是在某种程度上和父类不同,不然没必要定义一个新类,下面看下如何添加父类没有的方法或者覆盖父类的方法。
2.添加方法:
添加方法就是再子类中添加父类中没有的方法。
只需要在子类中定义一个新的函数方法即可。
1# 定义一个类
2>>> class Vehicle:
3... def __init__(self , category):
4... self.category = category
5...
6... def get_info(self):
7... return f"交通工具类别为:{self.category}。"
8
9# 从父类继承并添加新方法
10>>> class Car(Vehicle):
11... def description(self):
12... print("这是子类中添加的方法。")
13
14>>> a_car = Car("小汽车")
15>>> a_car.get_info()
16'交通工具类别为:小汽车。'
17>>> a_car.description()
18这是子类中添加的方法。
3.覆盖方法:
3.1 覆盖实例方法:
当子类中定义的方法与父类中的方法同名时,父类的方法会因子类中方法的覆盖而失效。
1# 定义一个类
2>>> class Vehicle:
3...
4... def __init__(self , category):
5... self.category = category
6...
7... def get_info(self):
8... return f"交通工具类别为:{self.category}。"
9
10# 从父类继承
11>>> class Car(Vehicle):
12... def description(self):
13... print("这是子类中添加的方法。")
14...
15... def get_info(self , brand):
16... return f"这是一辆品牌为{brand}的{self.category}。"
17
18>>> a_car = Car("小汽车")
19>>> a_car.get_info("Audi")
20'这是一辆品牌为Audi的小汽车。'
3.2 调用被覆盖的父类方法:
如果在子类中执行覆盖方法的同时,需要调用下父类被覆盖的方法,就需要通过下面分方式直接调用父类中的方法:
1FatherClassName.method(self , arguments)
例如:
1# 定义一个类
2>>> class Vehicle:
3...
4... def __init__(self , category):
5... self.category = category
6...
7... def get_info(self):
8... return f"交通工具类别为:{self.category}。"
9
10# 从父类继承
11>>> class Car(Vehicle):
12... def description(self):
13... print("这是子类")
14...
15... def get_info(self , brand):
16... print("调用父类中被子类覆盖的方法——" , Vehicle.get_info(self))
17... return f"这是一辆品牌为{brand}的{self.category}。"
18
19>>> a_car = Car("小汽车")
20>>> a_car.get_info("Audi")
21调用父类中被子类覆盖的方法—— 交通工具类别为:小汽车。
22'这是一辆品牌为Audi的小汽车。'
3.3 覆盖初始化方法:
上面的示例中覆盖了一个实例方法,类中的初始化方法也可以被覆盖:
1# 定义一个类
2>>> class Vehicle:
3...
4... def __init__(self , category):
5... self.category = category
6...
7... def get_info(self):
8... return f"交通工具类别为:{self.category}。"
9
10# 从父类继承
11>>> class Car(Vehicle):
12... def __init__(self , category):
13... self.category = chr(8730) + category + chr(8730)
14...
15... def get_info(self , brand):
16... return f"这是一辆品牌为{brand}的{self.category}。"
17
18>>> a_car = Car("小汽车" )
19>>> a_car.get_info("Audi")
20'这是一辆品牌为Audi的√小汽车√。'
4.多重继承:
子类可以继承自多个父类。
1class DerivedClassName(FatherClassName1 , FatherClassName2 , ......)
如果子类引用了不属于自己的方法或者特性,那么Python就会在所有父类中查找。如果不止一个父类拥有同名的方法或者特性,会根据方法解析顺序(深度优先,从左到右)决定子类继承哪个父类的方法或者特性。
例如下面示例中的搜寻顺序为:
-
如果在AutonomousCar当前类中没有找到,就会搜寻第一个传递的父类Car类。
-
如果在Car类没有找到,就会搜寻Car类的父类。
-
如果Car类的所有父类都没有找到,就会搜寻第二个传递的父类AI类。
-
如果AI类的所有父类都没有找到,就会搜寻第三个传递的父类(本次实例没有),依次类推,直到找到为止。
-
如果都没有找到就会报错。
每个Python类都有一个特殊方法mro(),可以返回一个类列表,用于查找该类对象的方法或特性,还有一个类似的特性__mro__,是由这些类组成的元祖。
1>>> class Vehicle:
2... def get_info(self):
3... return "Vehicle类。"
4
5>>> class Car(Vehicle):
6... pass
7
8>>> class AI():
9... def get_info(self):
10... return "AI类。"
11
12>>> class AutonomousCar(AI , Car):
13... pass
14
15>>> AutonomousCar.mro()
16[__main__.AutonomousCar, __main__.Car, __main__.Vehicle, __main__.AI, object]
17>>> autonomous_car = AutonomousCar()
18>>> autonomous_car.get_info()
19'Vehicle类。'
调换下父类的传递顺序,可以看到输出结果不一样。
1>>> class AutonomousCar(AI , Car):
2... pass
3
4>>> AutonomousCar2.mro()
5[__main__.AutonomousCar2, __main__.AI, __main__.Car, __main__.Vehicle, object]
6>>> autonomous_car_2 = AutonomousCar2()
7>>> autonomous_car_2.get_info()
8'AI类。'
5.super()函数:
如果子类需要调用父类的方法,也可以使用super()函数。
5.1 应用方式:
3.2中的示例可以修改为以下代码:
1# 定义一个类
2>>> class Vehicle:
3...
4... def __init__(self , category):
5... self.category = category
6...
7... def get_info(self):
8... return f"交通工具类别为:{self.category}。"
9
10# 从父类继承
11>>> class Car(Vehicle):
12... def description(self):
13... print("这是子类")
14...
15... def get_info(self , brand):
16... print("调用父类中被子类覆盖的方法——" , super().get_info()) # 修改部分
17... return f"这是一辆品牌为{brand}的{self.category}。"
18
19>>> a_car = Car("小汽车")
20>>> a_car.get_info("Audi")
21调用父类中被子类覆盖的方法—— 交通工具类别为:小汽车。
22'这是一辆品牌为Audi的小汽车。'
初始化方法也可以使用super()函数。
1# 定义一个类
2>>> class Vehicle:
3...
4... def __init__(self , category):
5... self.category = chr(8730) + category + chr(8730)
6...
7... def get_info(self):
8... return f"交通工具类别为:{self.category}。"
9
10# 从父类继承
11>>> class Car(Vehicle):
12... def __init__(self , category , brand):
13... super().__init__(category) # 使用super()函数调用父类中的初始化方法
14... self.brand = brand
15...
16... def get_info(self):
17... return f"这是一辆品牌为{self.brand}的{self.category}。"
18
19>>> a_car = Car("小汽车" , "Audi")
20>>> a_car.get_info()
21'这是一辆品牌为Audi的√小汽车√。'
5.2 注意事项:
如果类的继承关系比较复杂时,使用FatherClassName.method()
方法很容易出现父类方法被调用多次的情况,而使用super()
方法则可以避免上述情况发生,保证父类方法只被调用一次。
例如下面这种继承关系,Student类派生出两个子类MaleStudent类和FemaleStudent类,由这两个类又派生出一个子类ThisStudent类。
使用FatherClassName.method()
方法时,Student类中的方法被调用了两次:
1# 定义类
2>>> class Student:
3...
4... def __init__(self , name):
5... self.name = name
6...
7... def get_info(self):
8... print(self.name)
9
10# 定义类——>父类为Student
11>>> class MaleStudent(Student):
12...
13... def get_info(self):
14... Student.get_info(self)
15... print("MaleStudent类。")
16
17# 定义类——>父类为Student
18>>> class FemaleStudent(Student):
19...
20... def get_info(self):
21... Student.get_info(self)
22... print("FemaleStudent类。")
23
24# 定义类——>父类为MaleStudent+FemaleStudent
25>>> class ThisStudent(MaleStudent , FemaleStudent):
26...
27... def get_info(self):
28... MaleStudent.get_info(self)
29... FemaleStudent.get_info(self)
30... print("ThisStudent类。")
31
32>>> one_student = ThisStudent("Tom")
33>>> one_student.get_info()
34Tom
35MaleStudent类。
36Tom
37FemaleStudent类。
38ThisStudent类。
使用super()
方法时,Student类中的方法只被调用了一次:
1# 定义类
2>>> class Student:
3...
4... def __init__(self , name):
5... self.name = name
6...
7... def get_info(self):
8... print(self.name)
9
10# 定义类——>父类为Student
11>>> class MaleStudent(Student):
12...
13... def get_info(self):
14... super().get_info()
15... print("MaleStudent类。")
16
17# 定义类——>父类为Student
18>>> class FemaleStudent(Student):
19...
20... def get_info(self):
21... super().get_info()
22... print("FemaleStudent类。")
23
24# 定义类——>父类为MaleStudent+FemaleStudent
25>>> class ThisStudent(MaleStudent , FemaleStudent):
26...
27... def get_info(self):
28... super().get_info()
29... print("ThisStudent类。")
30
31>>> one_student = ThisStudent("Tom")
32>>> one_student.get_info()
33Tom
34FemaleStudent类。
35MaleStudent类。
36ThisStudent类。
本篇文章来源于微信公众号: 码农设计师