第2章Python序列序列是程序设计中经常用到的数据存储方式,几乎每一种程序设计语言都提供了表格数据结构,如C和Basic中的一维、多维数组等。Python提供的序列类型在所有程序设计语言中是最丰富,最灵活,也是功能最强大的。序列是一系列连续值,它们通常是相关的,并且按一定顺序排列。Python中常用的序列结构有列表、元组、字典、字符串、集合以及range等等。除字典和集合之外,列表、元组、字符串等序列均支持双向索引,第一个元素下标为0,第二个元素下标为1,以此类推;最后一个元素下标为-1,倒数第二个元素下标为-2,以此类推。2.1列表列表是Python中内置可变序列,是一个元素的有序集合,列表中的每一个数据称为元素,列表的所有元素放在一对中括号“[”和“]”中,并使用逗号分隔开;当列表元素增加或删除时,列表对象自动进行扩展或收缩内存,保证元素之间没有缝隙;在Python中,一个列表中的数据类型可以各不相同,可以同时分别为整数、实数、字符串等基本类型,甚至是列表、元素、字典、集合以及其他自定义类型的对象。例如:[10,20,30,40]['crunchyfrog','rambladder','larkvomit']['spam',2.0,5,[10,20]][['file1',200,7],['file2',260,9]]列表方法方法说明list.append(x)将元素x添加至列表尾部list.extend(L)将列表L中所有元素添加至列表尾部list.insert(index,x)在列表指定位置index处添加元素xlist.remove(x)在列表中删除首次出现的制定元素list.pop([index])删除并返回列表对象指定位置的元素list.clear()删除列表中所有元素,但保留列表对象,该方法在Python2中没有list.index(x)返回值为x的首个元素的下标list.count(x)返回指定元素x在列表中的出现次数list.reverse()对列表元素进行原地逆序list.sort()对列表元素进行原地排序list.copy()返回列表对象的浅拷贝,该方法在Python2中没有2.1.1列表创建与删除如同其他类型的Python对象变量一样,使用“=”直接将一个列表赋值给变量即可创建列表对象,例如:a_list=['a','b','mpilgrim','z','example']a_list=[]#创建空列表或者,也可以使用list()函数将元组、range对象、字符串或其他类型的可迭代对象类型的数据转换为列表。例如:a_list=list((3,5,7,9,11))a_list[3,5,7,9,11]list(range(1,10,2))[1,3,5,7,9]list('helloworld')['h','e','l','l','o','','w','o','r','l','d']x=list()#创建空列表x[]2.1.1列表创建与删除上面的代码中再次用到了内置函数range(),这是一个非常有用的函数,后面会多次用到,该函数语法为range([start,]stop[,step])内置函数range()接收3个参数,第一个参数表示起始值(默认为0),第二个参数表示终止值(结果中不包括这个值),第三个参数表示步长(默认为1),该函数在Python3.x中返回一个range可迭代对象,在Python2.x中返回一个包含若干整数的列表。另外,Python2.x还提供了一个内置函数xrange()(Python3.x中不提供该函数),语法与range()函数一样,但是返回xrange可迭代对象,类似于Python3.x的range()函数,其特点为惰性求值,而不是像range()函数一样返回列表。例如下面的Python2.7.8代码:range(10)[0,1,2,3,4,5,6,7,8,9]xrange(10)xrange(10)list(xrange(10))[0,1,2,3,4,5,6,7,8,9]2.1.1列表创建与删除使用Python2.x处理大数据或较大循环范围时,建议使用xrange()函数来控制循环次数或处理范围,以获得更高的效率。例如下面的Python2.7.8代码对range()和xrange()的运行效率进行了简单的对比。importtimeimportmathstart=time.time()forjinrange(100000000):1+1printtime.time()-startstart=time.time()forjinxrange(100000000):1+1printtime.time()-start上面的代码运行结果为15.733999967611.73399996762.1.1列表创建与删除列表推导式也是一种常用的快速生成符合特定要求列表的方式。当不再使用时,使用del命令删除整个列表,如果列表对象所指向的值不再有其他对象指向,Python将同时删除该值。dela_lista_listTraceback(mostrecentcalllast):Filepyshell#6,line1,inmodulea_listNameError:name'a_list'isnotdefined正如上面的代码所展示的一样,删除列表对象a_list之后,该对象就不存在了,再次访问时将抛出异常“NameError”提示访问的对象名不存在。2.1.2列表元素的增加(1)可以使用“+”运算符来实现将元素添加到列表中的功能。虽然这种用法在形式上比较简单也容易理解,但严格意义上来讲,这并不是真的为列表添加元素,而是创建一个新列表,并将原列表中的元素和新元素依次复制到新列表的内存空间。由于涉及大量元素的复制,该操作速度较慢,在涉及大量元素添加时不建议使用该方法。aList=[3,4,5]aList=aList+[7]aList[3,4,5,7]2.1.2列表元素的增加(2)使用列表对象的append()方法,原地修改列表,是真正意义上的在列表尾部添加元素,速度较快,也是推荐使用的方法。aList.append(9)aList[3,4,5,7,9]为了比较“+”和append()这两种方法的速度差异,请看以下代码:importtimeresult=[]start=time.time()foriinrange(10000):result=result+[i]print(len(result),',',time.time()-start)result=[]start=time.time()foriinrange(10000):result.append(i)print(len(result),',',time.time()-start)2.1.2列表元素的增加在上面的代码中,分别重复执行10000次“+”运算和append()方法为列表插入元素并比较这两种方法的运行时间。在代码中,使用time模块的time()函数返回当前时间,然后运行代码之后计算时间差。由于各种运行时的原因,多次运行上面的代码得到的结果会有微小的差别,其中一次运行的结果如下。可以看出,这两个方法的速度相差还是非常大的,使用append()方法比使用“+”运算快约70倍,相差两个数量级。10000,0.2180120944976806610000,0.0030000209808349612.1.2列表元素的增加Python采用的是基于值的自动内存管理方式,当为对象修改值时,并不是真的直接修改变量的值,而是使变量指向新的值,这对于Python所有类型的变量都是一样的。a=[1,2,3]id(a)20230752a=[1,2]id(a)203382082.1.2列表元素的增加对于列表、集合、字典等可变序列类型而言,情况稍微复杂一些。以列表为例,列表中包含的是元素值的引用,而不是直接包含元素值。如果是直接修改序列变量的值,则与Python普通变量的情况是一样的,而如果是通过下标来修改序列中元素的值或通过可变序列对象自身提供的方法来增加和删除元素时,序列对象在内存中的起始地址是不变的,仅仅是被改变值的元素地址发生变化。2.1.2列表元素的增加a=[1,2,4]b=[1,2,3]a==bFalseid(a)==id(b)Falseid(a[0])==id(b[0])Truea=[1,2,3]id(a)25289752a.append(4)id(a)25289752a.remove(3)a[1,2,4]id(a)25289752a[0]=5a[5,2,4]id(a)252897522.1.2列表元素的增加(3)使用列表对象的extend()方法可以将另一个迭代对象的所有元素添加至该列表对象尾部。通过extend()方法来增加列表元素也不改变其内存首地址,属于原地操作。例如,继续上面的代码执行下面的代码,其中id()函数的返回结果可能与您的执行结果不相同,这是正常的。a.extend([7,8,9])a[5,2,4,7,8,9]id(a)25289752aList.extend([11,13])aList[3,4,5,7,9,11,13]aList.extend((15,17))aList[3,4,5,7,9,11,13,15,17]id(a)252897522.1.2列表元素的增加(4)使用列表对象的insert()方法将元素添加至列表的指定位置。aList.insert(3,6)aList[3,4,5,6,7,9,11,13,15,17]2.1.2列表元素的增加应尽量从列表尾部进行元素的增加与删除操作。列表的insert()可以在列表的任意位置插入元素,但由于列表的自动内存管理功能,insert()方法会涉及到插入位置之后所有元素的移动,这会影响处理速度,类似的还有后面介绍的remove()方法以及使用pop()函数弹出列表非尾部元素和使用del命令删除列表非尾部元素的情况。因此,除非有必要,否则应尽量避免在列表中间位置插入和删除元素的操作,而是优先考虑使用前面介绍的append()方法和下一小节介绍的pop()方法。2.1.2列表元素的增加importtimedefInsert():a=[]foriinrange(10000):a.insert(0,i)defAppend():a=[]foriinrange(10000):a.append(i)start=time.time()foriinrange(10):Insert()print'Insert:',time.time()-startstart=time.time()foriinrange(10):Append()print'Append:',time.time()-start运行结果如下:Insert:0.578000068665Append:0.03099989891052.1.2列表元素的增加(5)使用乘法来扩展列表对象,将列表与整数相乘,生成一个新列表,新列表是原列表中元素的重复。aList=[3,5,7]bList=aListid(aList)57091464id(bList)57091464aList=aList*3aList[3,5,7,3,5,7,3,5,7]bList[3,5,7]id(aList)57092680id(bList)570914642.1.2列表元素的增加如要注意的是,当使用“*”运算符将包含列表的列表重复并创建新列表时,并不创建元素的复制,而是创建已有对象的引用。因此,当修改其中一个值时,相应的引用也