样例数据

Sarah Sweeney,2002-6-17,2:58,2.58,2:39,2-25,2-55,2:54,2.18,2:55,2:55,2:22,2-21,2.22

需要将数据整理,实现人名+出生日期+成绩的输出

以往的做法是:

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)

def get_coach_data(filename):
    try:
        with open(filename) as f:
            data = f.readline()
        return(data.strip().split(','))
    except IOError as ioerr:
        print('File error: ' + str(ioerr))
        return(None)

sarah = get_coach_data('sarah2.txt')

(sarah_name, sarah_dob) = sarah.pop(0), sarah.pop(0)

print(sarah_name + "'s fastest times are: " +
        str(sorted(set([sanitize(t) for t in sarah]))[0:3]))

这次加入了字典的做法

字典将数据值与键关联:

key   -->   value
Name        "sarah sweeney"
DOB         "2002-6-17"
Times       "[2:58,2.58,2:39,2-25,2-55,2:54,2.18,2:55,2:55,2:22,2-21,2.22]"

创建字典的方式可以是

cleese = {} #大括号!!

也可以是

palin = dict()

关联key和value的话是

cleese['Name'] = 'John Cleese'  # 一个key 对应一个字符串

或者

cleese['Name'] = ['John Cleese','John Cleese1','John Cleese2','John Cleese3','John Cleese4'] #一个key对应一个list

或者

cleese = {'Name':'abc','Address':'asdasdasda'}  #注意是用冒号

另外数据值与key关联后,需要访问数据值里面的某个数据项的话,可以是

cleese['Name'][-1] 

类似多维数组使用。

代码改为

#!/usr/bin/python
# -*- coding: utf-8 -*-


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)

def get_coach_data(filename):
        try:
                with open(filename) as f:
                        data = f.readline()
                return(data.strip().split(','))
        except IOError as ioerr:
                print('File error:' + str(ioerr))
                return(None)

sarah = get_coach_data('sarah2.txt')

sarah_data={}
sarah_data['Name'] = sarah.pop(0)   #根据数据结构,第一个数据是名字,第二个是生日,第二个之后是成绩,所以分别将相关数据赋值到字典里面。
sarah_data['DOB'] = sarah.pop(0)
sarah_data['Times'] = sarah

print(sarah_data['Name'] + "'s fastest times are: " + str(sorted(set([sanitize(t) for t in sarah_data['Times']]))[0:3]))

字典的方法优势在于合理使用数据结构。是否知道何时使用列表而何时使用字典,这正式从好的程序员中区分出优秀程序员的一个标准。
字典其实也叫“映射”,“散列”,“关联数组”

为了更加方便的处理多个人的成绩的数据,所以将字典数据转移到函数里面去,直接通过函数生成出字典,并返回需要的数据

#!/usr/bin/python
# -*- coding: utf-8 -*-


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)

def get_coach_data(filename):
        try:
                with open(filename) as f:
                        data = f.readline()
                templ = data.strip().split(',')
                return({'Name':templ.pop(0),    #这里就是字典
                        'DOB':templ.pop(0),
                        'Times':str(sorted(set([sanitize(t) for t in templ]))[0:3])})
        except IOError as ioerr:
                print('File error:' + str(ioerr))
                return(None)

sarah = get_coach_data('sarah2.txt')
james = get_coach_data('james2.txt')

print(sarah['Name'] + "'s fastest times are: " + sarah['Times'])

这就是将代码和数据打包在一起。特定函数应用特定数据。

更加正规的做法是建立类。

类是面向对象oop编程模型的东西,类的概念在这里不详细描述。

类可以

1.降低复杂性
2.方便维护和扩展

python的类需要有一个self参数,这个参数是用来标识是属于哪个对象实例的

例如:

class Athlete:
    def __init__(self,value=0):
        self.thing = value      #定义这个类的属性thing
    def how_big(self)           #定义一个方法how_big
        return(len(self.thing))

btw:init 是类的python固定实现方法,所以是必须的。

你写的代码                   -->     python执行的代码
d = Athlete("Holy Grail")           Athlete.__init__(d,"Holy Grail")
                                    |         |      |  
                                    类       方法    目标标识符 
                                    |         |     |
d.how_big()                         Athlete.how_big(d)

代码改为:

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)

class Athlete:
    def __init__(self, a_name, a_dob=None, a_times=[]):
        self.name = a_name      #通过类的属性来定义name,dob和times
        self.dob = a_dob
        self.times = a_times

    def top3(self):
        return(sorted(set([sanitize(t) for t in self.times]))[0:3])

def get_coach_data(filename):
    try:
        with open(filename) as f:
            data = f.readline()
        templ = data.strip().split(',')
        return(Athlete(templ.pop(0), templ.pop(0), templ))
    except IOError as ioerr:
        print('File error: ' + str(ioerr))
        return(None)

james = get_coach_data('james2.txt')
julie = get_coach_data('julie2.txt')
mikey = get_coach_data('mikey2.txt')
sarah = get_coach_data('sarah2.txt')

print(james.name + "'s fastest times are: " + str(james.top3()))
print(julie.name + "'s fastest times are: " + str(julie.top3()))
print(mikey.name + "'s fastest times are: " + str(mikey.top3()))
print(sarah.name + "'s fastest times are: " + str(sarah.top3()))

科普:

1.通过在各个对象的属性中保留原始数据,可以支持类扩展来满足将来的其他需求。如果处理数据并作为对象初始化代码的一部分,说明你已对程序员将如何使用这个类做出了假设,而日后这些假设肯定会对你造成障碍。

在类里面增加一个灵活的增加成绩数据的函数

可以是增加单个成绩,或是增加多个成绩
单个成绩用add_time,传入的是字符串
多个成绩是add_times,传入的是list

以下是单个成绩的样例:

#!/usr/bin/python
# -*- coding: utf-8 -*-

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 add_time(self,time_value):      #这里就是了。
                self.times.append(time_value)
        def top3(self):
                return (sorted(set([sanitize(t) for t in self.times]))[0:15])
        def add_times(self,list_of_times):
                self.times.extend(list_of_times)

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)

def get_coach_data(filename):
        try:
                with open(filename) as f:
                        data = f.readline()
                templ = data.strip().split(',')
                return (Athlete(templ.pop(0),templ.pop(0),templ))
        except IOError as ioerr:
                print('File error:' + str(ioerr))
                return(None)

sarah = get_coach_data('sarah2.txt')

sarah.add_time('2.88')      #这里调用
print(sarah.name + "'s fastest times are: " + str(sarah.top3()))    #输出结果会改变

观察到这个类有点像list,所以有重复制造车轮的嫌疑,并且功能单一,所以决定集成list类

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)

class AthleteList(list):    #继续list类,所以这里要写list的名字

    def __init__(self, a_name, a_dob=None, a_times=[]):
        list.__init__([])   #这里需要初始化list类
        self.name = a_name
        self.dob = a_dob
        self.extend(a_times)    #因为集成list类了,所以这里可以直接使用list的extend方法

    def top3(self):
        return(sorted(set([sanitize(t) for t in self]))[0:3])

def get_coach_data(filename):
    try:
        with open(filename) as f:
            data = f.readline()
        templ = data.strip().split(',')
        return(AthleteList(templ.pop(0), templ.pop(0), templ))
    except IOError as ioerr:
        print('File error: ' + str(ioerr))
        return(None)

james = get_coach_data('james2.txt')
julie = get_coach_data('julie2.txt')
mikey = get_coach_data('mikey2.txt')
sarah = get_coach_data('sarah2.txt')

print(james.name + "'s fastest times are: " + str(james.top3()))
print(julie.name + "'s fastest times are: " + str(julie.top3()))
print(mikey.name + "'s fastest times are: " + str(mikey.top3()))
print(sarah.name + "'s fastest times are: " + str(sarah.top3()))

原文引用:http://www.godblessyuan.com/2015/05/03/head_first_python_chapter_6_lea...


线上猛如虎
2.2k 声望178 粉丝

你们都有梦想的,是吧.怀抱着梦想并且正朝着梦想努力的人,寻找着梦想的人,我想为这些人加油呐喊!