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 (, , ,
24 , , )
25 '''