WELCOME

不积跬步,无以至千里;不积小流,无以成江海。

Python面向对象--继承

1.继承

在现实生活中,继承一般指的是子女继承父辈的财产,父辈有的财产,子女能够直接使用。

程序里的继承
继承是面向对象软件设计中的一个概念,与多态、封装共为面向对象的三个基本特征。继承可以使得子类具有父类的属性和方法或者重新定义、追加属性和方法等。

在程序中,继承描述的是多个类之间的所属关系。
如果一个类A里面的属性和方法可以复用,则可以通过继承的方式,传递到类B里。
那么类A就是基类,也叫做父类;类B就是派生类,也叫做子类。

 

格式:

继承:
 Student,Employee,Doctor都属于人类
 具有相同的属性,相同的代码存在冗余,可读性不高

 提取相同的代码,子类继承父类--->Person
 Student,Employee,Doctor===》继承Person
 class 子类名(父类名):
    pass

 

 1 class Person:
 2     def __init__(self, name, age):
 3         self.name = name
 4         self.age = age
 5 
 6     def eat(self):
 7         print(self.name + '正在吃饭...')
 8 
 9     def run(self):
10         print(self.name + '正在跑步...')
11 
12 
13 class Student(Person):
14     pass
15 
16 
17 class Employee(Person):
18     pass
19 
20 
21 class Doctor(Person):
22     pass
23 
24 
25 stu = Student('tom', 18)
26 stu.run()
27 stu.eat()
28 
29 e = Employee('jack', 20)
30 e.run()
31 e.eat()
32 
33 d = Doctor('smith', 21)
34 d.run()
35 e.eat()
36 
37 '''
38 tom正在跑步...
39 tom正在吃饭...
40 jack正在跑步...
41 jack正在吃饭...
42 smith正在跑步...
43 jack正在吃饭...
44 '''

 

2.super

 1、如果类中不定义__init__,调用父类 super class 的__init__
 2、如果类继承父类也需要定义自己的__init___,就需要在当前类的__init__调用父类的__init__
 3、如何调用父类的__init__:
    (1).super().__init__(参数)
    (2).super(类名,对象).__init__(参数)
 4、如果父类有某个方法,子类也定义一个同样的方法,则只读取子类的方法。默认搜索原则:先找当前子类,再找父类。
    如父类的Person也有eat(),但子类的Student类也有eat(),则先调用子类Student类的eat(),再调用父类的eat()

 5、当父类提供的方法不满足子类的需求时,就需要在子类中定义一个同名的方法,这种行为就叫做重写
 6、子类的方法中也可以调用父类的方法,调用方法:super().方法名
 例如Student类的eat,:super.eat()

 

 1 class Person:
 2     def __init__(self, name, age):
 3         self.name = name
 4         self.age = age
 5 
 6     def eat(self):
 7         print(self.name + '正在吃饭...')
 8 
 9     def run(self):
10         print(self.name + '正在跑步...')
11 
12 
13 class Student(Person):
14     def __init__(self, name, age, clazz):
15         super().__init__(name, age)
16         self.clazz = clazz
17         print('---------->student的init')
18 
19     def study(self, course):
20         print('{}正在学{}'.format(self.name, course))
21 
22     def eat(self, food):
23         super().eat()
24         print('{}正在吃饭...喜欢吃:{}'.format(self.name, food))
25 
26 
27 class Employee(Person):
28     def __init__(self, name, age, salary, manager):
29         super().__init__(name, age)
30         self.salary = salary
31         self.manager = manager
32 
33 
34 class Doctor(Person):
35     def __init__(self, name, age, patients):
36         super(Doctor, self).__init__(name, age)
37         self.patients = patients
38 
39 
40 stu = Student('tom', 18, 'python1906')
41 stu.run()
42 stu.eat('万州烤鱼')
43 stu.study('python基础')
44 e = Employee('jack', 20, 10000, 'king')
45 # e.run()
46 
47 list1 = ['张三', '李四', '王五']
48 d = Doctor('smith', 21, list)
49 # e.run()
50 
51 '''
52 tom正在跑步...
53 tom正在吃饭...
54 tom正在吃饭...喜欢吃:万州烤鱼
55 tom正在学python基础
56 '''

 

小练习

编写一个简单的工资管理程序,系统可以管理以下四类人,工人(rorker)、销售员(salesman)
所有的员工都具有员工号,姓名,工资等属性,
有设置姓名,获取姓名,获取员工号,计算工资等方法。
1)工人:工人具有工作小时数和时薪的属性,工资计算法方法为工作小时数*时薪。
2)销售员:具有销售额和提成比例的属性,工资计算方法为销售额*提成比例。
请根据以上要求设计合理的类,完成以下功能:
    1)添加所有类型的人员
    2)计算月薪
    3)显示所有人工资情况

 

 1 class Person:
 2     def __init__(self, no, name, salary):
 3         self.no = no
 4         self.name = name
 5         self.salary = salary
 6 
 7     def __str__(self):
 8         msg = '工号:{},姓名:{},本月工资:{}'.format(self.no, self.name, self.salary)
 9         return msg
10 
11     def getSalary(self):
12         return self.salary
13 
14 
15 class Worker(Person):
16 
17     def __init__(self, no, name, salary, hours, per_hour):
18         super(Worker, self).__init__(no, name, salary)
19         self.hours = hours
20         self.per_hours = per_hour
21 
22     def getSalary(self):
23         money = self.hours * self.per_hours
24         self.salary += money
25         return self.salary
26 
27 
28 class Salesman(Person):
29     def __init__(self, no, name, salary, salemoney, percent):
30         super(Salesman, self).__init__(no, name, salary)
31         self.salemoney = salemoney
32         self.percent = percent
33 
34     def getSalary(self):
35         money = self.salemoney * self.percent
36         self.salary += money
37         return self.salary
38 
39 
40 #  创建子类对象
41 
42 worker = Worker('007', 'tom', 2000, 180, 18)
43 salary = worker.getSalary()
44 print('007号月薪是:', salary)
45 print(worker)
46 
47 saler = Salesman('008', 'jack', 5000, 5000000, 0.003)
48 salary = saler.getSalary()
49 print('008号月薪是:', salary)
50 print(saler)
51 
52 '''
53 007号月薪是: 5240
54 工号:007,姓名:tom,本月工资:5240
55 008号月薪是: 20000.0
56 工号:008,姓名:jack,本月工资:20000.0
57 '''

 

 

3.多继承

Python中针对类提供了一个内置属性__mro__可以用来查看方法的搜索顺序。
MRO 是method resolution order的简称,主要用于在多继承时判断方法属性的调用顺序。
print(C.__mro__)
输出结果:

(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
在调用方法时,按照__mro__的输出结果从左至右的顺序查找。
如果再当前类中找到方法,就直接执行,不再向下搜索。
如果没有找到,就顺序查找下一个类中是否有对应的方法,如果找到,就直接执行,不再继续向下搜索。
如果找到了最后一个类,依然没有找到方法,程序就会报错。

 

新式类和旧式(经典)类
object是Python中所有对象的基类,提供了一些内置的属性和方法,可以时候用dir函数查看。

新式类:以object为基类的类,推荐使用
经典类:不以object为基类的类,不推荐使用
在 Python3.x 以后定义类时,如果没有指定父类,这个类会默认继承自 object,所以,python3.x版本定义的类都是新式类。
在Python2.x中定义类时,如果没有指定父类,则不会继承自object.
为了保证代码在Python2.x和Python3.x中都能够运行,在定义类时,如果一个类没有父类,建议统一继承自'object'

class 类名(object):
    pass

 

 

 1 class P2:
 2     def foo(self):
 3         print('p2--->foo')
 4 
 5 
 6 class C1(P1, P2):
 7     pass
 8 
 9 
10 class C2(P1, P2):
11     def bar(self):
12         print('C2--->bar')
13 
14 
15 class D(C1, C2):
16     pass
17 
18 d = D()
19 
20 print(D.__mro__)
21 
22 '''
23 (<class '__main__.D'>, <class '__main__.C1'>, <class '__main__.C2'>,
24  <class '__main__.P1'>, <class '__main__.P2'>, <class 'object'>)
25 '''

 

继承搜索顺序

 1 class A:
 2     def foo(self):
 3         print('p1--->foo')
 4 
 5     def bar(self):
 6         print('p1--->bar')
 7 
 8 
 9 class B:
10     def foo(self):
11         print('p2--->foo')
12 
13 
14 class C(A):
15     pass
16 
17 
18 class D(A):
19     def bar(self):
20         print('C2--->bar')
21 
22 
23 class E(C, B):
24     pass
25 
26 
27 class F(C, B, D):
28     pass
29 
30 
31 class G(D, B):
32     pass
33 
34 
35 g = G()
36 
37 print(F.__mro__)
38 
39 '''
40 (<class '__main__.F'>, <class '__main__.C'>, <class '__main__.B'>, 
41 <class '__main__.D'>, <class '__main__.A'>, <class 'object'>)
42 '''

F的查找顺序,先C-->B-->D-->A-->object

 

 先按继承的顺序寻找,到最后一个再按往上一层级的寻找

posted @ 2022-03-31 18:25  Ambitious~  阅读(72)  评论(0)    收藏  举报