Python中的列表知识点汇总
Pythonlist
在介绍Pythontuple时,我使用了类比的方法,将其比做一个袋子,您可以在袋子中存放不同的东西。Pythonlist与此非常类似,因此,它的功能与袋子的功能也非常类似。但有一点是不同的,即您可以使用方括号创建list,如清单1所示。
清单1.在Python中创建一个list
>>>l=[0,1,2,3,4,5,6,7,8,9] >>>l [0,1,2,3,4,5,6,7,8,9] >>>type(l) <type'list'> >>>el=[]#Createanemptylist >>>len(el) 0 >>>sl=[1]#Createasingleitemlist >>>len(sl) 1 >>>sl=[1,]#Create asingleitemlist,aswithatuple >>>len(sl) 1
本例展示如何创建包含从0到9(包括0和9)的简单list,以及如何创建一个空列表和一个包含单个条目的列表。如果您还记得的话,创建单个条目的tuple还需要在单个条目后面跟一个逗号。这是区分单个条目tuple与方法调用的必要条件,这一点将在以后的文章中详细讨论。而对于list,则是不必要的,尽管也允许使用单个逗号。
与往常一样,要获取有关Python主题的更多信息,您可以使用内置的帮助解释器,例如,清单2展示了如何开始list类的帮助描述。
清单2.获取有关list的帮助
>>>help(list) Helponclasslistinmodule__builtin__: classlist(object) |list()->newlist |list(sequence)->newlistinitializedfromsequence'sitems | |Methodsdefinedhere: | |__add__(...) |x.__add__(y)<==>x+y | |__contains__(...) |x.__contains__(y)<==>yinx | ...
如果仔细观察清单2中对list类的描述,您会看到其中提供了两个不同的构造函数:一个没有参数,另一个接受一个序列类作为参数。因此,使用构造函数及方括号简化符号,可以创建list。这就提供了很大的灵活性,原因是您可以方便地将现有的序列,如tuple或string转换为list,如清单3所示。不过,请注意,传递的参数必须是序列——并且不只是对象序列——否则将会出现错误。对于任何序列类型,您都可以使用len方法容易地查找序列中条目的数量。
清单3.直接创建list对象
>>>l=list() >>>type(l) <type'list'> >>>len(l) 0 >>>l [] >>>l=list((0,1,2,3,4,5,6,7, 8,9))#Createalistfromatuple >>>l [0,1,2,3,4,5,6,7,8,9] >>>len(l) 10 >>>l=list([0,1,2,3,4,5,6,7,8,9])#Createalistfromalist >>>l [0,1,2,3,4,5,6,7,8,9] >>>len(l) 10 >>>l=list(0,1,2,3,4,5,6,7, 8,9)#Error:Mustpassinasequence Traceback(mostrecentcalllast): File"<stdin>",line1,in? TypeError:list()takesatmost1argument(10given) >>>l=list("0123456789")#Createalistfromastring >>>l ['0','1','2','3','4','5','6','7','8','9'] >>>type(l) <type'list'> >>>len(l) 10
正如您看到的,创建list是很容易的,如果还没有尝试过,现在可以试一试。您不仅能够将序列直接传递给构造函数,还可以将拥有元组或字符串的变量传递给list构造函数。
很明显,序列较为有用的主要原因是它可以非常方便地访问序列中的条目。如果还记得对tuple的讨论,便知道可以在序列中一次访问一个条目或者通过将条目切片来访问条目。Pythonlist也可以使用相同的技术,如清单4所示。
清单4.从list访问条目
>>>l=list([0,1,2,3,4,5,6,7,8,9]) >>>l[0]#Getthefirstiteminthelist 0 >>>type(l[0]) <type'int'> >>>l[5]#Getthesixthiteminthelist 5 >>>l[1:5]#Getthesecondthroughfifthitems [1,2,3,4] >>>type(l[1:5]) <type'list'> >>>l[0::2]#Geteveryseconditem [0,2,4,6,8] >>>l[0],l[1],l[2] (0,1,2)
在以前的文章中已经了解到,切片是一个非常有用的概念,其一般形式为l[start:end:step],其中start和end分别是开始和结束索引,step是在切片时要跨过的条目数量。此外,还可以对结束索引使用负值,即从序列的结尾往回计数。另一个有用的功能是以一种很合适的方式处理错误(如超过序列的长度)。如前一个例子所示,您还可以选择忽略切片中使用的三个值中的一个或多个值。例如,我在切片l[0::2]中没有使用结束索引。
可变的序列
在本文的开头,我提到过list和tuple之间的主要区别在于list是一个可变的序列,这就意味着您不但可以方便地访问list中的条目,而且可以方便地修改它们。但这会引起一个并发症状:您只能修改序列中的条目。若要向序列中添加条目(而不仅仅是修改条目),可使用append方法,如清单5所示。
清单5.修改list
>>>l=[] >>>l[0]=0#Thelistisempty Traceback(mostrecentcalllast): File"<stdin>",line1,in? IndexError:listassignmentindexoutofrange >>>l.append(0) >>>l [0] >>>l[0]=1 >>>l [1]
正如前一个例子所演示的,尝试修改不存在的list条目会导致出现错误。这一点意义重大,并演示了Python方法生成错误的情况。当问题较为严重时,将会产生一个错误,如果问题较小并且可以很容易地处理,则忽略它。
异构的可变序列
您可能想了解更为复杂的修改。通过综合切片知识以及如何修改list的知识,您应该已经获得了非常重要的见识:可以通过多种方式修改列表。就像tuple一样,list也可以持有不同类型的数据(或不同类型的对象),这就是我所说的异构的可变序列。这两种功能在清单6中进行了更完整的描述。
清单6.异构的可变list
>>>l=[0,1,2,3,4,5,6,7,8,9] >>>l [0,1,2,3,4,5,6,7,8,9] >>>l[2]=2 >>>type(l[2]) <type'int'> >>>l[2]="two"#Changethetypeofanelement >>>,ype(l[2]) <type'str'> >>>l [0,1,'two',3,4,5,6,7,8,9] >>>l[2]=l[2:5]*2 >>>l [0,1,['two',3,4,'two',3,4],3,4,5,6,7,8,9] >>>del(l[2])#Removesingleelement >>>l [0,1,3,4,5,6,7,8,9] >>>l[1:3]=[]#Removeaslice >>>l [0,4,5,6,7,8,9]
修改list中的条目相当容易:您可以适当地设置条目的值,甚至设置成另一种不同的类型,如string或另一list。您还可以使用重复运算符,可以将该运算符识别为乘法运算符,以便从小片段中构建更大的列表。
前面的例子向您展示了如何向list中添加元素,以及如何修改list中的条目。前一个例子还演示了如何从list中删除对象。删除条目的第一个方法是使用del方法。使用此方法可以删除一个条目或一个条目范围。您还可以使用灵活而强大的切片方法从list中删除切片。
数组
在前一个例子中您可以看到,list可以包含另一个list作为条目。如果扩展此例子,您可能想知道每个条目由一个list替换将会发生什么样的事情。结果是一个数组,或者从更加数学方面来讲是一个矩阵。清单7展示了如何使用list保持二维(2-D)或三维(3-D)数组。
清单7.list作为一个数组
>>>al=[[0,1,2],[3,4,5],[6,7,8]] >>>al [[0,1,2],[3,4,5],[6,7,8]] >>>al[0][0]#Firstelementin2Darray 0 >>>al[2][2]#Lastelementin2Darray 8 >>>al[1][2] 5 >>>al=[[[0,1],[2,3]],[[4,5],[6,7]]] >>>al [[[0,1],[2,3]],[[4,5],[6,7]]] >>>al[0][0][1] 1 >>>len(al)#Lengthofouterdimension 2 >>>len(al[0])#Lengthofmiddledimension 2 >>>len(al[0][0])#Lengthofinnerdimension 2
其他列表操作
list对象具有许多可以应用于现有列表的有用方法。例如,您可以反转list中的所有条目或排序list。不过,要记住这些操作的一个重点在于,它们是就地操作,这意味着它们会修改调用它们所针对的list。因此,如果您尝试创建新列表,并将其设置为对这些方法之一调用所产生的结果,则会得到一个空列表。
list除可以用于模拟数组外,还可以用于模拟其他数据结构。例如,append和pop方法对list函数的操作要么是先进先出(FIFO)数据结构(也称为队列),要么是后进先出(LIFO)数据结构(也称为堆栈)。通过允许您将条目设置为从list中弹出(删除并返回),pop方法支持这些功能。如果弹出list的第一项,则是一个队列;反之,如果弹出list的最后一项,则是一个堆栈,如清单8所示。
清单8.操纵list
>>>l=[0,1,2,3,4,5,6,7,8,9] >>>id(l)#Thisistheobjectidforourcurrentlist 4525432 >>>l.reverse()#Reversethelist >>>l [9,8,7,6,5,4,3,2,1,0] >>>id(l)#Theidisthesame,modifiedlistinplace. 4525432 >>>l.sort()#Sortthelistinnumericalorder >>>l [0,1,2,3,4,5,6,7,8,9] >>>id(l)#Modifiedtheexistinglist 4525432 >>>l.index(5)#Sameasl[5] 5 >>>l.count(0)#How manytimesdoes'0'occurinthelist 1 >>>l.pop()#Takeoffthelastitem(Stack) 9 >>>l [0,1,2,3,4,5,6,7,8] >>>l.pop(5)#Takeoutthefifthelement 5 >>>l [0,1,2,3,4,6,7,8] >>>l.pop(0)#Takethefirstitemoffthelist(Queue) 0 >>>l [1,2,3,4,6,7,8]
列表:切片和切块
本文介绍了list,它是一个容器对象,可以方便地进行修改,而且可以持有不同类型的数据。由于它具有相当的灵活性,因此list是Python编程语言中最常用的结构之一已不足为怪。list像一个口袋,可以容纳不同类型的数据,并可以根据需要更改。您可以像使用数组一样使用list,以有组织的方式容纳数据;您还可以像使用队列或堆栈一样使用list。在以后的文章中还将更为深入地探索这一灵活性,并介绍强大的编程技术,即列表理解。