课程连接
https://aistudio.baidu.com/aistudio/course/introduce/7073
定义:class 子类名(父类名):
说明:(1)如果子类有新增属性,需要在子类__init__方法中,调用父类的__init__
(2)如果子类没有新增的属性,子类不需要写__init__方法
使用方式:对象名 = 子类名()
继承的好处:代码重用,升级功能(重写),新增功能(新的方法)
例:
数据文件loren.txt内容:loren,2011-11-3,270,3.59,4.11,3:11,3:23,4-10,3-23,4:10,4.21,4-21
# 取出loren.txt中的数据并进行粉刺处理
def get_coach_data(filename):
with open(filename) as f:
line = f.readline()
return line.strip().split(',')
# 定义Athlete类
class Athlete:
def __init__(self, a_name, a_dob = None, a_times = []):
self.name = a_name
self.dob = a_dob
self.times = a_times
def top3(self):
return sorted(set([self.sanitize(t) for t in self.times]))[0: 3]
def sanitize(self, time_string):
if '-' in time_string:
splitter = '-'
elif ':' in time_string:
splitter = ':'
else:
return (time_string)
(mins, secs) = time_string.split(splitter)
return (mins + '.' + secs)
# 定义橄榄球运动员类继承Athlete类
class Rugby(Athlete):
def __init__(self, a_name, a_bod, a_squat, a_times):
# 新增squat属性,调用父类__init__
Athlete.__init__(self, a_name, a_bod, a_times)
self.squat = a_squat # 深蹲次数
# 继承后下面两个函数就在Rugby类中,不用再写
# def top3(self):
# return sorted(set([self.sanitize(t) for t in self.times]))[0: 3]
# def sanitize(self, time_string):
# if '-' in time_string:
# splitter = '-'
# elif ':' in time_string:
# splitter = ':'
# else:
# return (time_string)
# (mins, secs) = time_string.split(splitter)
# return (mins + '.' + secs)
# 测试输出
loren = get_coach_data('./loren.txt')
rugby = Rugby(loren.pop(0), loren.pop(0), loren.pop(0), loren)
print('姓名:%s, 生日:%s, 深蹲:%s个, 最快的3次成绩:%s' %(rugby.name, rugby.dob, rugby.squat, rugby.top3()))
# 输出结果:姓名:loren, 生日:2011-11-3, 深蹲:270个, 最快的3次成绩:['3.11', '3.23', '4.10']
子类方法与父类方法完全相同,子类若重写了父类的方法,则子类对象调用方法时就是调用的自己类中重新的方法。
例:
# 修改top3方法,取出最慢的三次记录,可以重复
class Rugby(Athlete):
def __init__(self, a_name, a_bod, a_squat, a_times):
Athlete.__init__(self, a_name, a_bod, a_times)
self.squat = a_squat
def top3(self):
return sorted([self.sanitize(t) for t in self.times])[-3: ]
# 测试输出
loren = get_coach_data('./loren.txt')
rugby = Rugby(loren.pop(0), loren.pop(0), loren.pop(0), loren)
print('姓名:%s, 生日:%s, 深蹲:%s个, 最慢的3次成绩:%s' %(rugby.name, rugby.dob, rugby.squat, rugby.top3()))
# 输出结果:姓名:loren, 生日:2011-11-3, 深蹲:270个, 最慢的3次成绩:['4.11', '4.21', '4.21']
多态性:一个事物多种形态
多态的好处:减少重复代码,分离经常改变的代码与不经常改变的代码,使得代码可维护性提高。
例:
有多种运动员,它们的top3完全不同,我们需要为每种运动员定义一个子类,调用会是一堆重复的代码。
# 定义其它种类运动员继承Athlete类,取出最快的3次记录,可以重复
class OtherAthlete(Athlete):
def __init__(self, a_name, a_bod, a_squat, a_times):
Athlete.__init__(self, a_name, a_bod, a_times)
self.squat = a_squat
def top3(self):
return sorted([self.sanitize(t) for t in self.times])[0: 3]
# 有多种运动员,为每种运动员定义一个子类,调用会是一堆重复的代码
mark1 = get_coach_data('./mark.txt')
mark2 = get_coach_data('./mark1.txt')
mark3 = get_coach_data('./mark2.txt')
mark1 = OtherAthlete(mark1.pop(0), mark1.pop(0), mark1.pop(0), mark1)
mark2 = OtherAthlete(mark2.pop(0), mark2.pop(0), mark2.pop(0), mark2)
mark3 = OtherAthlete(mark3.pop(0), mark3.pop(0), mark3.pop(0), mark3)
print('姓名:%s, 生日:%s, 深蹲:%s个, 最快的3次成绩:%s' %(mark1.name, mark1.dob, mark1.squat, mark1.top3()))
print('姓名:%s, 生日:%s, 深蹲:%s个, 最快的3次成绩:%s' %(mark2.name, mark2.dob, mark2.squat, mark2.top3()))
print('姓名:%s, 生日:%s, 深蹲:%s个, 最快的3次成绩:%s' %(mark3.name, mark3.dob, mark3.squat, mark3.top3()))
# 运行结果
# 姓名:mark,生日:2010-2-4,深蹲:300个,最快的3次成绩:['3.11', '3.11', '3.23']
# 姓名:mark,生日:2010-2-4,深蹲:111个,最快的3次成绩:['3.11', '3.11', '3.23']
# 姓名:mark,生日:2010-2-4,深蹲:222个,最快的3次成绩:['3.11', '3.11', '3.23']
# 有多种运动员,为每种运动员定义一个子类,调用会是一堆重复的代码
loren = get_coach_data('./loren.txt')
mark = get_coach_data('./mark.txt')
loren = Rugby(loren.pop(0), loren.pop(0), loren.pop(0), loren)
mark = OtherAthlete(mark.pop(0), mark.pop(0), mark.pop(0), mark)
print(loren.name)
print(loren.dob)
print(loren.squat)
print(loren.top3())
print(mark.name)
print(mark.dob)
print(mark.squat)
print(mark.top3())
# 运行结果
# loren
# 2011-11-3
# 270
# ['4.11', '4.21', '4.21']
# mark
# 2010-2-4
# 300
# ['3.11', '3.11', '3.23']
下面是使用多态的代码:
# print_rugby()的参数athlete,athlete.name,athlete.top3()的行为由athlete的子类决定。
loren = get_coach_data('mywork/loren.txt')
mark = get_coach_data('mywork/mark.txt')
loren = Rugby(loren.pop(0),loren.pop(0),loren.pop(0),loren)
mark = OtherAthlete(mark.pop(0),mark.pop(0),mark.pop(0),mark)
def print_rugby(athlete):
print(athlete.name)
print(athlete.dob)
print(athlete.squat)
print(athlete.top3())
print_rugby(loren)
print_rugby(mark)
# 运行结果
# loren
# 2011-11-3
# 270
# ['4.11', '4.21', '4.21']
# mark
# 2010-2-4
# 300
# ['3.11', '3.11', '3.23']
定义:class 子类名(父类名1, 父类名2, ...):
使用方式:对象名 = 子类名()
例:
class Father():
def talk(self):
print("---爸爸的表达能力---")
class Mather():
def smart(self):
print("---妈妈聪明的头脑---")
class Child(Father, Mather):
pass
child = Child()
child.talk()
child.smart()
# 运行结果
# ---爸爸的表达能力---
# ---妈妈聪明的头脑---
多个父类有相同的属性或方法名,应该避免。
# 只会输出第一个父类的__init__方法和talk方法
class Father():
def __init__(self):
self.color = 'black'
def talk(self):
print("---爸爸的表达能力---")
class Mather():
def __init__(self):
self.color = 'white'
def talk(self):
print("--妈妈也能表达")
def smart(self):
print("---妈妈聪明的头脑---")
class Child(Father, Mather):
pass
child2 = Child()
child2.talk()
child2.smart()
print(child2.color)
# 运行结果
# ---爸爸的表达能力---
# ---妈妈聪明的头脑---
# black
将上面的代码进行改进。
class Father():
def __init__(self):
self.color = 'black'
def talk(self):
print("---爸爸的表达能力---")
class Mather():
def __init__(self):
self.height = 170
def smart(self):
print("---妈妈聪明的头脑---")
class Child(Father,Mather):
def __init__(self):
Father.__init__(self)
Mather.__init__(self)
child1 = Child()
child1.talk()
child1.smart()
print(child1.color)
print(child1.height)
# 运行结果
# ---爸爸的表达能力---
# ---妈妈聪明的头脑---
# black
# 170
在每个需要Athlete的时候,都需要把Athlete类的定义复制粘贴到要用的代码上方。
# 导入sys模块
import sys
# 将模块athlete.py添加到模块搜索路径(路径/athlete.py)
sys.path.append('路径')
# import athlete
# print(dir(athlete))
# 导入athlete模块,使用athlete模块下的所有代码
from athlete import *
loren = get_coach_data('mywork/loren.txt')
mark = get_coach_data('mywork/mark.txt')
loren = Rugby(loren.pop(0),loren.pop(0),loren.pop(0),loren)
mark = OtherAthlete(mark.pop(0),mark.pop(0),mark.pop(0),mark)
def print_rugby(athlete):
print(athlete.name)
print(athlete.dob)
print(athlete.squat)
print(athlete.top3())
print_rugby(loren)
print_rugby(mark)
# 运行结果
# loren
# 2011-11-3
# 270
# ['4.11', '4.21', '4.21']
# mark
# 2010-2-4
# 300
# ['3.11', '3.11', '3.23']