首页Python【Python基础】20....

【Python基础】20.类的继承


本系列文章配套代码获取有以下三种途径:

  • 可以在以下网站查看,该网站是使用JupyterLite搭建的web端Jupyter环境,因此无需在本地安装运行环境即可使用,首次运行浏览器需要下载一些配置文件(大约20M):

https://returu.github.io/Python_Basic/lab/index.html
链接: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类。


本篇文章来源于微信公众号: 码农设计师

RELATED ARTICLES

欢迎留下您的宝贵建议

Please enter your comment!
Please enter your name here

- Advertisment -

Most Popular

Recent Comments