数据集合体
数据集合体 很多程序都需要处理大量类似数据的集合 文档中的大量单词 学校学生, 企业客户 实验得到的数据 ...... 2 2
数据集合体 大量同类型数据组成一个整体 Python提供集合体数据类型: list, tuple, dict, set, file 一次物理实验得到的大批数据 一个文档中的大量单词 一个画布上的所有图形 一个学校里的所有学生, ...... Python提供集合体数据类型: list, tuple, dict, set, file 3 3 3
数据集合体 回顾: 输入一批数据求平均值的程序 无需保存数据: 用累积变量sum和count即可 但:求中位数和标准差需要保存全部数据. 用很多独立变量保存? 中位数, 一组数据按从小到大(或从大到小)的顺序依次排列,处在中间位置的一个数(或最中间两个数据的平均数) 标准差(Standard Deviation) ,也称均方差(mean square error),是各数据偏离平均数的距离的平均数。标准差是方差的算术平方根。标准差能反映一个数据集的离散程度。平均数相同的,标准差未必相同。 4 4 4
数据结构 构成一个整体的大量数据成员一般是"相关的",即其间存在某种逻辑关系 逻辑关系可以体现在存储结构中 不但要表示各数据成员,还要表示其间逻辑关系 逻辑关系可以体现在存储结构中 例如:字符串"HELLO" 连续存储的序列结构即可表示5个字符间的关系 分散独立存储5个字符,则无法表示其间关系 存储结构必须有利于对数据的操作 5 5 5
序列 序列:多个数据项按次序排列而形成的集合体数据 Python的str,list,tuple都是序列 次序是排列先后次序,并非数据项的值的比较 Python的str,list,tuple都是序列 6 6
序列的操作 通用的序列操作 s1 + s2 s * n或n * s s[i]或s[i:j]或s[i:j:k] len(s) min(s) max(s) x in s或x not in s 7 7 7
字符串 回顾:字符串是字符序列. 基本操作:索引,子串,合并,重复... string库 不能修改 字符串作为对象 方法 8 8 8
例:字符串对象方法 >>> s = "I think, therefore I am." >>> s.count('I') 2 >>> s.find('re') 12 >>> (s.lower()).replace('i','I') 'I thInk, therefore I am.' >>> s.split() ['I', 'think,', 'therefore', 'I', 'am.'] >>> s.islower() False 9 9 9
列表 有没有一个对象能包含很多数据?Yes! 列表(List):是一种数据集合体 如range(10) = [0,1,2,3,4,5,6,7,8,9] 又如string.split(“This is it.”) = [‘This’,’is’,’it’] 列表(List):是一种数据集合体 是数据的有序序列 整体用一个名字表示: 如seq 各成员通过下标(索引)引用: 如seq[3] 10 10
列表与字符串 回顾: Python字符串是序列,可通过索引引用 列表与字符串的区别: 列表的成员可以是任何数据类型, 而字符串中只能是字符; 列表的成员可修改, 而字符串不能修改 11 11 11
列表与数组 很多编程语言提供数组(array)类型. Python列表与数组的区别: 列表是动态的,而数组是定长的 列表元素可以是混合类型的,而数组元素是同类型的
列表操作 对字符串的操作也可应用于列表: 列表删除: del <seq>[<start>:<end>] 合并: <seq> + <seq> 重复: <seq> * <int_expr> 索引: <seq>[<index_expr>] 分段: <seq>[<start>:<end>] 长度: len(<seq>) 迭代: for <var> in <seq>: ... 列表删除: del <seq>[<start>:<end>] 13 13 13
列表操作(续) 应用于列表的专门方法: 隶属: x in <list>
编程实例:stats.py # stats.py from math import sqrt def getNumbers(): def mean(nums): def stdDev(nums, xbar): def median(nums): def main(): data = getNumbers() xbar = mean(data) std = stdDev(data, xbar) med = median(data) print ...... if __name__ == ’__main__’: main()
例:列表对象的方法 >>> a = ['Irrational',[3.14,2.718],'pi and e'] >>> a.sort() >>> a [[3.14, 2.718], 'Irrational', 'pi and e'] >>> a[0].reverse() [[2.718, 3.14], 'Irrational', 'pi and e'] >>> a.insert(2,'number') [[2.718, 3.14], 'Irrational', 'number', 'pi and e'] >>> print a.pop(0) [2.718, 3.14] ['Irrational', 'number', 'pi and e'] 16
列表与类结合使用 类将一些数据与操作封装成一个对象 列表将一些同类对象组合成整体 这两者的结合可以表示任意复杂的数据集合体.
编程实例:对DieView的改进 将骰子的7个点构成一个列表.(原为7个独立变量) 好处:对整个列表进行操作时,代码变得简单,因为可以应用循环语句.如: for pip in self.pips: pip.setFill(self.background) for i in [0,3,6]: self.pips[i].setFill(self.foreground) 根据掷出的value决定点亮骰子哪些点:可以使用表驱动的写法(见下页) 18
编程实例:对DieView的改进一(续) for pip in self.pips: self.pip.setFill(self.background) if value == 1: on = [3] elif value == 2: on = [0,6] elif value == 3: on = [0,3,6] elif value == 4: on = [0,2,4,6] elif value == 5: on = [0,2,3,4,6] else: on = [0,1,2,4,5,6] for i in on: self.pips[i].setFill(self.foreground)
编程实例:对DieView的改进二(续) onTable = [ [], [3], [2,4], [2,3,4], [0,2,4,6], [0,2,3,4,6], [0,1,2,4,5,6] ] for pip in self.pips: self.pip.setFill(self.background) on = onTable[value] for i in on: self.pips[i].setFill(self.foreground) 注:这个onTable是不变的,可以作为类的实例变量,由__init__初始化. 20
编程实例:计算器 程序 = 数据结构的集合 + 处理数据结构的算法的集合 因此: 整个应用程序本身可看作对象! 编程实例: 计算器 每个计算器是一个对象 21 21
元组 元组:用圆括号包围的一组值. 元组也是序列,适用所有序列操作. 类似列表但内容不可修改. 例如:创建计算器按钮的代码: bSpecs = [(2,1,’0’), (3,1,’.’), (1,2,’1’), (2,2,’2’), (3,2,’3’), (4,2,’+’), (5,2,’-’), (1,3,’4’), (2,3,’5’), (3,3,’6’), (4,3,’*’), (5,3,’/’), (1,4,’7’), (2,4,’8’), (3,4,’9’), (4,4,’<-’),(5,4,’C’)] self.buttons = [] for (cx,cy,label) in bSpecs: self.buttons.append(Button(self.win,Point(cx,cy),.75,.75,label)) # create the larger ’=’ button self.buttons.append(Button(self.win, Point(4.5,1), 1.75, .75, "="))
元组 若序列创建后就不再改变,则可表示为元组:效率高,防止误操作. Python也将元组实现为对象. 方法: <元组>.index(x) <元组>.count(x) tuple( )可将字符串和列表转换成元组.
例:元组 >>> x = 1,2,3 # 将元组(省略了括号)赋值给x >>> x (1, 2, 3) >>> x,y,z = 1,2,3 # 实为元组赋值 1 >>> y,z (2, 3) >>> t = ("Lucy",("Math",90)) >>> t[1][1] 90 >>> tuple('hello') ('h', 'e', 'l', 'l', 'o') 24
集合:无序集合体 Python提供set类型 set值的创建: 元素无序 元素不重复 用{...} 25
例:集合值的创建 >>> {1,2,3} set([1, 2, 3]) >>> s = {1,1,2,2,2,3,3} >>> s >>> set('set') set(['s', 'e', 't']) >>> set([1,1,1,2,1]) set([1, 2]) >>> set((1,2,1,1,2,3,4)) set([1, 2, 3, 4]) >>> set() set([]) 26
集合运算 基本就是数学中的集合运算 27
例:集合运算 >>> s1 = {1,2,3,4,5} >>> s2 = {2,4,6,8} >>> 6 in s1 False >>> s1 | s2 set([1, 2, 3, 4, 5, 6, 8]) >>> s1 & s2 set([2, 4]) >>> s1 - s2 set([1, 3, 5]) >>> s1 |= s2 >>> s1 >>> len(s2) 4 28
集合对象 Python以面向对象方式实现set 29
字典:无序集合体 在集合体中查找数据: 序列采用索引查找:根据位置检索 字典采用关联查找:根据给定数据检索与之关联的数据 “键-值”查找:按给定的键,检索相关联的值 name : John
字典:无序集合体 Python提供字典类型, 用来存储“键-值对”. 键类型常用字符串, 整数; 值类型则任意. 存储:按内部最有效的方式, 不保持创建顺序 31
字典例 缩略语字典 查找: abbr[‘etc’]返回cetera 修改: abbr[‘etc’] = ‘et cetera’ abbr = {‘etc’:’cetera’, ‘cf’:’confer’, ’ibid’:’ibidem’} 查找: abbr[‘etc’]返回cetera 修改: abbr[‘etc’] = ‘et cetera’ 32
字典例 月份映射表 month = {1:’Jan’, 2:’Feb’, 3:’March’, 4:’April’} 显示: print month[1] 增加键值对: month[4] = ‘April’ 33
字典的操作 字典创建 检索:从ki检索vi 值可修改 d = {k1:v1, k2:v2, ... , kn:vn} 或dict() d[ki] 值可修改 d[ki] = <new_value> 34
例:字典创建 >>> d = {'Lucy':1234,'Tom':5678,'Mary':1357} >>> print d {'Mary': 1357, 'Lucy': 1234, 'Tom': 5678} >>> d1 = dict(name="Lucy",age=8,hobby=("bk","gm")) >>> d1 {'hobby': ('bk', 'gm'), 'age': 8, 'name': 'Lucy'} >>> d2 = dict([[(5,1),'Worker'],[(6,1),'Child'],[(7,1),'CPC']]) >>> d2 {(5, 1): 'Worker', (6, 1): 'Child', (7, 1): 'CPC'} 35
例:字典检索 >>> d1["name"] 'Lucy' >>> d1["age"] 8 >>> d1["hobby"] ('bk', 'gm') >>> d1["gender"] Traceback (most recent call last): File "<pyshell#22>", line 1, in <module> d1["gender"] KeyError: 'gender' >>> d2[(6,1)] 'Child' >>> d2[7,1] 'CPC' 36
例:字典修改 修改与指定键对应的值 删除键值对:del <dict>[<key>] 如果指定的键不存在,则相当于添加键值对 >>> d1["age"] = 9 >>> d1 {'hobby': ('bk', 'gm'), 'age': 9, 'name': 'Lucy'} >>> d1["gender"] = "F" {'hobby': ('bk','gm'), 'age':9, 'name':'Lucy', 'gender':'F'} 删除键值对:del <dict>[<key>] del d[k] 37
字典对象的方法 Python将字典实现为对象,支持的方法: 键存在性:<dict>.has_key(<key>) 键列表:<dict>.keys() 值列表:<dict>.values() 键值对列表:<dict>.items() 清空字典:<dict>.clear()
例:字典对象的方法 >>> d1.keys() ['hobby', 'age', 'name', 'gender'] >>> d1.values() [('bk', 'gm'), 9, 'Lucy', 'F'] >>> d1.items()[0:2] [('hobby', ('bk', 'gm')), ('age', 9)] >>> d1.has_key("gender") True 39
编程实例:词频统计 统计文档中单词的出现次数 用字典结构: 单词首次出现时字典里查不到会出错: counts:{<单词>:<频度计数>} 用很多累积变量显然不好! 单词首次出现时字典里查不到会出错: try: counts[w] = counts[w] + 1 except KeyError: counts[w] = 1
编程实例:词频统计(续) 对大文档, 为每个单词输出频度没有意义. 如何输出前n个最频繁的单词? 对<单词>:<频度>列表按频度排序 <list>.sort()不行 比较函数cmp(x,y):根据x在y之前或相等或之后分别返回-1,0,1 自定义比较函数,并用于排序: def myCmp((w1,c1),(w2,c2)):...... <list>.sort(myCmp) wordfreq.py 41
作业 Most languages do not have the flexible built-in list (array) operations that Python has. Write an algorithm for each of the following Python operations and test your algorithm by writing it up in a suitable function. For example, as a function, reverse(myList) should do the same as myList.reverse(). Obviously, you are not allowed to use the corresponding Python method to implement your function. (a) count(myList, x) (like myList.count(x)) (b) isin(myList, x) (like x in myList)) (c) index(myList, x) (like myList.index(x)) (d) reverse(myList) (like myList.reverse()) (e) sort(myList) (like myList.sort())
作业
End 44