新需求
橄榄球教练Roger,拿出了自己的数据结构,我们的队员除了速度训练,还需要进行力量的练习。既然你的类表现的不错,我能不能用呢?
loren,2011-11-3,270,3.59,4.11,3:11,3:23,4-10,3-23,4:10,4.21,4-21
In [ ]
def get_coach_data(filename):
with open(filename) as f:
line = f.readline()
return line.strip().split(',')
In [ ]
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)
In [ ]
#定义橄榄球运送员类
class Rugby(Athlete):
def __init__(self,a_name,a_bod,a_squat,a_times):
#调用父类__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)
In [ ]
loren = get_coach_data('mywork/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()))
姓名:2011-11-3,生日:270,深蹲:3.59个,最块的3次成绩:['3.11', '3.23', '4.10']
如何使用
定义:
class 子类名(父类名):
情况1,如果子类有新增的属性,那么需要在子类__init方法中,调用父类的__init__
情况2,如果子类没有新增的属性,子类不需要写__init__方法
使用:
对象名 = 子类名(参数)
继承的好处:代码重用,升级功能(重写),新增功能(新的方法)
新需求
作为橄榄球队的教练,我不太在意最快的3个记录,top3我只想知道3次最长时间记录就可以了,重复也行。
In [ ]
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:]
In [ ]
loren = get_coach_data('mywork/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()))
姓名:2011-11-3,生日:270,深蹲:3.59个,最慢的3次成绩:['4.11', '4.21', '4.21']
方法重写
子类方法与父类方法完全相同,子类若重写了父类的方法,则子类对象调用方法时就是调用的自己类中重新的方法。
问题
如果有其他的教练,只需要top3中的,3个最短记录呢(可以重复)?有更多的教练对top3的更多要求呢?
In [ ]
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]
In [ ]
mark = get_coach_data('mywork/mark.txt')
mark = OtherAthlete(mark.pop(0),mark.pop(0),mark.pop(0),mark)
print('姓名:%s,生日:%s,深蹲:%s个,最快的3次成绩:%s' %(mark.name,mark.dob,mark.squat,mark.top3()))
姓名:mark,生日:2010-2-4,深蹲:300个,最快的3次成绩:['3.11', '3.11', '3.23']
问题
又来10个各种各样的运动员,他们的top3完全不同,代码看起来是这样的。
我需要为每种远动员定义一个子类,调用的时候是一堆重复的代码。
In [ ]
mark1 = get_coach_data('mywork/mark.txt')
mark2 = get_coach_data('mywork/mark1.txt')
mark3 = get_coach_data('mywork/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']
In [ ]
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)
print(loren.name)
print(loren.dob)
print(loren.squat)
print(loren.top3())
print(mark.name)
print(mark.dob)
print(mark.squat)
print(mark.top3())
2011-11-3
270
3.59
['4.11', '4.21', '4.21']
mark
2010-2-4
300
['3.11', '3.11', '3.23']
In [ ]
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)
2011-11-3
270
3.59
['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的子类决定。
多态的好处是:减少重复代码,分离经常改变的代码与不经常改变的代码,使得代码可维护性提高。
In [ ]
#如何优化创建对象的代码呢?
def obj_factory(name,filename):
with open(filename) as f:
line = f.readline()
templ = line.strip().split(',')
if name == 'r':
return Rugby(templ.pop(0),templ.pop(0),templ.pop(0),templ)
elif name == 'oa':
return OtherAthlete(templ.pop(0),templ.pop(0),templ.pop(0),templ)
oa = obj_factory('oa','mywork/mark.txt')
print(oa.name)
mark
多继承
In [ ]
class Father():
def talk(self):
print("---爸爸的表达能力---")
class Mather():
def smart(self):
print("---妈妈聪明的头脑---")
class Child(Father,Mather):
pass
child1 = Child()
child1.talk()
child1.smart()
---爸爸的表达能力---
---妈妈聪明的头脑---
In [ ]
#多个父类有相同的属性或方法名,这种情况应该避免
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
child1 = Child()
child1.talk()
child1.smart()
print(child1.color)
---爸爸的表达能力---
---妈妈聪明的头脑---
black
In [ ]
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类的定义复制粘贴要用的代码上方。
In [2]
import sys
sys.path.append('mywork')
# import athlete
# print(dir(athlete))
from athlete import *
import sys
导入sys模块 sys.path.append('work')
将模块athlete.py添加到模块搜索路径
from athlete import *
导入athlete模块,使用athlete模块下的所有代码
In [ ]
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)
2011-11-3
270
3.59
['4.11', '4.21', '4.21']
mark
2010-2-4
300
['3.11', '3.11', '3.23']
问题
如果有一个模块mymodule.py中也包含get_coach_data函数,该怎么区分这两个函数呢?
In [5]
import sys
sys.path.append('work')
from p1.mymodule import *
from p2.mymodule import *
import p1
import p2
p1.mymodule.demo()
p2.mymodule.demo()
p1 -- mymodule
p1 -- mymodule