Kelly教练每天在训练场忙的焦头烂额,根本没有时间摆弄计算机,需要人帮他处理选手的数据!
运动员在刻苦训练,每跑一个600米,kelly就会计时并将时间记录到计算机中的文本文件中,共有4个选手James、Sarah、Julie和Mikey,分别对应4个文件
james.txt 2-34,3:21,2,34,2.45,3.01,2:01,2:01,3:10,2-22
sarah.txt 2:58,2.58,2:39,2-25,2:55,2:54,2.18,2:55,2:55
julie.txt 2.59,2.11,2:11,2:23,3-10,2-23,3:10,3.21,3-21
mikey.txt 2:22,3.01,3:01,3.02,3:02,3.02,3:22,2.49,2:38
# 读取文件内容,按逗号进行切分
def get_coach_data(filename):
with open(filename) as f:
line = f.readline()
return line.strip().split(',')
# 输出读取文件的结果
times = get_coach_data('mywork/james.txt')
print('读取文件james.txt后的结果:\n')
print(times)
在这段代码中
filename为*文件路径*,是传入get_coach_data函数的参数
f 是一个自定义名字的*文件对象*
realine()方法表示读取文件的一行
line.strip().split(',')为链式函数写法,意思是,首先对line变量使用strip()方法,去掉首尾的 ' ' ,也就是空格;
然后再使用split()方法,将变量line中的所有 ',' 都删除,并以这些逗号作为分隔,生成一个新的列表并返回。
函数再把这个列表return并赋值给变量time,就可以以列表的形式得到文件中的内容。
在记录数据的时候出现了一些纰漏,分秒间的符号居然不一样
james.txt 2-34,3:21,2,34,2.45,3.01,2:01,2:01,3:10,2-22
分别出现了 ‘ - ’ , ‘ : ’ , ’ , ’ , ’ . '足足四种符号。
为了方便后续使用,Kelly教练希望我们规整一下数据
函数如下
def sanitize(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)
在这段代码中
time_string是之前提取的列表中的**单个元素**,也是传入的参数。
splitter是根据原数据的格式来确实分钟和秒的分隔符
(mins,secs) = time_string.split(splitter)
return (mins+'.'+secs)
通过split方法把分和秒先分开,传入mins和secs变量里,然后再返回,
**如果这里直接使用列表生成式,那么返回值可以直接组成一个列表**
也就是说,由于Python的简洁性,我们可以快速搞定数据的整理
包括规范化,排序,去重,提取想要的任何值
代码如下
# python,一句话搞定数据标准化,排序和去重
james_times = get_coach_data('mywork/james.txt')
print('一句话搞定数据标准化、排序、去重\n')
print(sorted(set([sanitize(t) for t in james_times]))[0:3])
# set函数去重,sorted函数排序,[0:3]切片列表同时提取最小的三个值
#[sanitize(t) for t in james_times]就是一个列表生成式
但是在以上代码中,我们为了得到James一个人的数据,新建了很多变量,当处理的人数变多的时候,代码会非常的繁琐且重复,怎么解决这个问题呢
这就要引进类的使用了
首先,类是什么呢?
类是一种模板,我们可以使用类来快速处理大量同类数据,这些数据要拥有一样的属性,比如这些运动员都拥有名字,生日,以及他们的成绩。
当我们给类赋予方法时,我们就可以使用这些方法快速批量处理数据,而且不需要大量重复的代码
更低的复杂性–>更少的bug–>更高的可维护性
类可以将数据与函数绑定在一起,使代码模块化
调用数据和函数,使用对象名.属性/方法的方式,使代码更加优雅
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([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)
在这段代码中
__init__方法用来绑定类需要的属性,他传入的参数既是属性值。
top3和sanitize方法都是类的方法。
在我们读取数据后,可以用以下代码快速处理James的数据
# 从文件中读取数据
james_new = get_coach_data('mywork/james_new.txt')
james_name = james_new.pop(0)
james_dob = james_new.pop(0)
james_times = james_new
# 创建Athlete对象
james = Athlete(james_name,james_dob,james_times)
print('姓名:%s,生日:%s,最快的3次成绩:%s' %(james.name,james.dob,james.top3()))
在这段代码中
我们使用了pop方法,这个方法的作用是弹出变量中的一个元素,当方法中的参数为空时,默认弹出最后一位元素
—————————————————————————————————
james = Athlete(james_name,james_dob,james_times)
这个过程叫实例化一个类,会生成一个实例化对象,也就是‘james’,我们可以通过james.name来调用他的name属性,就不需要在代码主体里生成一个james_name变量了
当我们有很多组数据需要处理时,可以这样进行实例化
julie_new = get_coach_data('mywork/julie_new.txt')
julie_name = julie_new.pop(0)
julie_dob = julie_new.pop(0)
julie_times = julie_new
james_new = get_coach_data('mywork/james_new.txt')
james_name = james_new.pop(0)
james_dob = james_new.pop(0)
james_times = james_new
julie = Athlete(julie_name,julie_dob,julie_times)
james = Athlete(james_name,james_dob,james_times)
实例化之后我们就可以自由调用对象的各种属性和方法了
class Athlete:
#运动员集训了,要买东西的同学要把地址改一下
address = '中国足球协会训练基地xx街xx号'
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)
julie_new = get_coach_data('mywork/julie_new.txt')
julie_name = julie_new.pop(0)
julie_dob = julie_new.pop(0)
julie_times = julie_new
james_new = get_coach_data('mywork/james_new.txt')
james_name = james_new.pop(0)
james_dob = james_new.pop(0)
james_times = james_new
julie = Athlete(julie_name,julie_dob,julie_times)
james = Athlete(james_name,james_dob,james_times)
print(julie.address)
print(james.address)
print(Athlete.address)
#直接使用对象名.属性名调用
除了类属性之外,我们还有类方法可以使用,只需要在新定义的方法前使用@classmethod标记就好
@classmethod
#说明下面的方法是类方法
def changeAddress(self):
self.address = '中国田径训练基地xx街xx号'
方法很简单,只需要在属性或方法前使用__(双下划线)就可以;
例如“__sanitize”
私有属性和方法是无法被外部调用的
所以当我们需要输出或者打印这些私有属性时,可以另在类中写一个方法,当我们调用这个方法的时候,就可以输出属性值
def sayName(self):
print(self.__name)