当前位置: 首页 > 后端技术 > Python

Python教程:高级功能

时间:2023-03-25 23:35:47 Python

1.切片L[0:3]表示从索引0开始到索引3,但不包括索引3。即索引0、1、2恰好是3个元素。如果第一个索引为0,也可以省略:>>>L=['Michael','Sarah','Tracy','Bob','Jack']>>>L[:3]['Michael','Sarah','Tracy']也可以从索引1开始取出2个元素:>>>L[1:3]['Sarah','Tracy']类似,因为Python支持L[-1]取firstlast元素,那么它也支持倒数切片,>>>L[-2:]['Bob','Jack']>>>L[-2:-1]['Bob']的索引倒数第二个元素是-1。切片操作非常有用。让我们首先创建一个0-99的序列:>>>L=list(range(100))[0,1,2,3,...,99]您可以通过切片轻松提取数字序列。例如前10个数:>>>L[:10][0,1,2,3,4,5,6,7,8,9]对于前10个数,每二取一:>>>L[:10:2][0,2,4,6,8]所有数字,每5个:>>>L[::5][0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95]甚至什么都不写,只写[:]来复制列表:>>>??L[:][0,1,2,3,...,99]元组也是一种列表,唯一的区别是元组是不可变的。因此,元组也可以通过切片来操作,但是操作的结果仍然是一个元组:>>>(0,1,2,3,4,5)[:3](0,1,2)字符串'xxx'也可以看作是一种列表,每个元素就是一个字符。因此,也可以对字符串进行切片操作,但操作的结果仍然是一个字符串:>>>'ABCDEFG'[:3]'ABC'在很多编程语言中,都为字符串提供了多种多样的截取函数(例如,substring),其实目的就是对字符串进行切片。Python没有字符串拦截功能。只需要切片即可完成,非常简单。S="abcdefg"print(S[:2])#abprint(S[::2])#acegprint(S[::3])#adg2.迭代如果给出一个列表或元组,我们可以通过循环遍历这个列表或元组,这种遍历我们称之为迭代(Iteration)。在Python中,迭代是通过for...in完成的,而在很多语言如C或Java中,迭代列表是通过下标完成的,Python的for循环抽象度高于Java的for循环,因为Python的for循环可以是不仅用于列表或元组,还用于其他可迭代对象。虽然list这个数据类型有下标,但是很多其他数据类型是没有下标的。但是只要是可迭代对象,不管有没有下标都可以迭代。例如,dict可以迭代:>>>d={'a':1,'b':2,'c':3}>>>forkeyind:...print(key)acb因为dict的存储不是按照list的顺序排列的,迭代出来的结果顺序很可能不一样。默认情况下,dict遍历键。如果要迭代value,可以在d.values()中使用forvalue,如果要同时迭代key和value,可以在d.items()中使用fork,v。由于字符串也是可迭代对象,因此也可以应用于for循环:>>>forchin'ABC':...print(ch)...ABC所以,当我们使用for循环时,我们只需要行动on一个可迭代对象,for循环是可以正常运行的,我们不太关心这个对象是列表还是其他数据类型。那么,如何判断一个对象是可迭代对象呢?方法是判断collections模块的Iterable类型:>>>fromcollectionsimportIterable>>>isinstance('abc',Iterable)#str是否为iterableTrue>>>isinstance([1,2,3],Iterable)#列表是否可迭代True>>>isinstance(123,Iterable)#整数是否可迭代False如果想为列表实现类似Java的下标循环怎么办?Python内置的enumerate函数可以把一个列表变成索引-元素对,这样索引和元素本身就可以在for循环中同时迭代:>>>fori,valueinenumerate(['A','B','C']):...在print(i,value)上面的for循环中,同时引用了两个变量,这在Python中很常见,比如下面的代码:>>>forx,yin[(1,1),(2,4),(3,9)]:...print(x,y)任何可迭代对象都可以作用于for循环,包括我们的自定义数据类型,只要满足迭代条件,就可以使用for循环。3.列表生成是ListComprehensions,这是一个非常简单但功能强大的Python内置生成器,可以用来创建列表。例如,要生成列表[1,2,3,4,5,6,7,8,9,10],您可以使用list(range(1,11))生成[1x1,2x2,3x3,...,10x10]怎么做呢?第一种方法是循环:>>>L=[]>>>forxinrange(1,11):...L.append(x*x)...>>>L[1,4,9,16,25,36,49,64,81,100]列表生成公式可以用一行语句代替循环生成上面的列表([1x1,2x2,3x3,...,10x10]):[x*xforxinrange(1,11)]写列表生成公式时,把要生成的元素x*x放在前面,后面是for循环,就可以创建列表,进行if判断即可在for循环之后添加,这样我们就可以只过滤掉偶数方块:>>>[x*xforxinrange(1,11)ifx%2==0][4,16,36,64,100]也可以使用两层循环,可以生成全排列:>>>[m+nformin'ABC'fornin'XYZ']['AX','AY','AZ','BX','BY','BZ','CX','CY','CZ']使用列表生成很少使用三层或更多层的循环,可以编写非常简洁的代码。比如列出当前目录下的所有文件和目录名,一行代码就可以实现>>>importos#导入os模块,模块的概念后面会讲到>>>[dfordinos.listdir('.')]#os.listdir可以列出文件和目录['.emacs.d','.ssh','.Trash','Adlm','Applications','Desktop','Documents','Downloads','Library','Movies','Music','Pictures','Public','VirtualBoxVMs','Workspace','XCode']for循环实际上可以使用两个或更多同时变量,比如dictitems()可以同时迭代key和value:>>>d={'x':'A','y':'B','z':'C'}>>>fork,vind.items():...print(k,'=',v)...y=Bx=Az=C因此,列表生成也可以使用两个变量来生成一个列表:>>>??d={'x':'A','y':'B','z':'C'}>>>[k+'='+vfork,vind.items()]['y=B','x=A','z=C']最后将列表中的所有字符串转换为小写:>>>L=['Hello','World','IBM','Apple']>>>[s.lower()forsinL]Exercise2L1=['Hello','World',18,'Apple',None]print([x.lower()ifisinstance(x,str)elsexforxinL1])4.Generator有了列表理解,我们可以直接创建一个列表。但是,由于内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用大量存储空间,而且如果我们只需要访问前几个元素,后面的大部分元素占用的空间都会被浪费掉。那么,如果列表元素可以按照一定的算法计算出来,我们是不是可以在循环中不断计算后面的元素呢?由于不必创建完整列表,因此可以节省大量空间。在Python中,这种while循环计算的机制被称为生成器:generator。创建生成器的方法有很多种。第一种方法很简单,只要把alistgeneration的[]改成(),就创建了一个generator:g=(x*xforxinrange(10))at0x1022ef630>创建L和g的区别只是最外层的[]和(),L是列表,g是生成器。如果要将它们一一打印出来,可以通过next()函数获取生成器的下一次返回值:next(g)generator保存算法,每次调用next(g)时,生成器的值计算g的下一个元素。如果在计算完最后一个元素之前没有更多元素,则会抛出StopIteration错误。连续调用next(g)也太变态了。正确的做法是使用for循环,因为generator也是一个可迭代对象:>>>g=(x*xforxinrange(10))>>>forninTheg:...print(n)发电机非常强大。如果计算算法比较复杂,不能用类似列表生成的for循环实现,也可以用函数实现。比如著名的斐波那契数列(Fibonacci),除了第一个和第二个数外,任何数都可以通过前两个数相加得到:1,1,2,3,5,8,13,21,34,...斐波那契数列不能用列表理解来写,但很容易用函数打印它:deffib(max):n,a,b=0,0,1whilen>>f=fib(6)生成器的执行流程与功能。函数是顺序执行的,遇到return语句或者函数语句的最后一行就返回。成为generator的函数在每次调用next()时执行,遇到yield语句就返回,再次执行时从上次返回的yield语句开始继续执行。尝试:在上面yieldb下面加一行print(b),调用fib(6),没有输出,只有遍历f的时候。举个简单的例子,定义一个依次返回数字1、3、5的生成器:defodd():print('step1')yield1print('step2')yield(3)print('step3')yield(5)调用生成器时,先生成一个生成器对象,然后使用next()函数不断获取下一个返回值:>>>o=odd()>>>next(o)step11>>>next(o)step23>>>next(o)step35>>>next(o)Traceback(最近调用last):文件“”,第1行,在StopIterationodd中不是一个普通的函数,而是一个生成器。执行过程中遇到yield会中断,下次继续执行。执行了3次yield后,没有yield可执行,所以第四次调用next(o)会报错。把函数改成generator之后,我们基本不用next()获取下一个返回值,而是直接用for循环迭代:>>>forninfib(6):...print(n)但是用for循环调用generator时,发现获取不到generator的return语句的返回值。如果要获取返回值,必须捕获StopIteration错误,返回值包含在StopIteration的值中:>>>g=fib(6)>>>whileTrue:...try:...x=next(g)...print('g:',x)...除了StopIterationase:...print('Generatorreturnvalue:',e.value)...breakg:1g:1g:2g:3g:5g:8Generator返回值:done理解生成器的工作原理,它在for循环的过程中不断计算下一个元素,并在合适的条件下结束for循环。对于由函数变来的生成器,当遇到return语句或者执行到函数体的最后一行时,就是结束生成器的指令,for循环随之结束。5、迭代器我们已经知道,可以直接应用于for循环的数据类型有以下几种:一种是集合数据类型,如list、tuple、dict、set、str等;另一个是generator,包括generator和一个带yield的generatorfunction。这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。>>>fromcollectionsimportIterable>>>isinstance([],Iterable)True>>>isinstance({},Iterable)True>>>isinstance('abc',Iterable)True>>>isinstance((xforxinrange(10)),Iterable)True>>>isinstance(100,Iterable)False可以用isinstance()判断一个对象是否是Iterable对象:而且生成器不仅可以作用于for循环,还可以被next()函数使用一直调用并返回下一个值,直到最后抛出一个StopIteration错误,表示无法返回下一个值。能被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。可以通过isinstance()来判断一个对象是否为Iterator对象:#学习中遇到问题没人回答?小编创建了一个Python学习交流群:711312441>>>fromcollectionsimportIterator>>>isinstance((xforxinrange(10)),Iterator)True>>>isinstance([],Iterator)False>>>isinstance({},Iterator)False>>>isinstance('abc',Iterator)False生成器都是Iterator对象,但是list、dict、str虽然是Iterable,但不是Iterator。您可以使用iter()函数将list、dict和str等可迭代对象转换为迭代器:>>>isinstance(iter([]),Iterator)True>>>isinstance(iter('abc'),Iterator)True你可能会问,为什么list、dict、str等数据类型不是Iterator?这是因为Python的Iterator对象代表一个数据流,Iterator对象可以被next()函数调用,不断返回下一条数据,直到没有数据时抛出StopIteration错误。这个数据流可以看作是一个有序的序列,但是我们无法预先知道序列的长度,只能通过next()函数不断的按需计算下一个数据,所以Iterator的计算是惰性的,只当需要时,只会在下一个数据返回时才计算。迭代器甚至可以表示无限的数据流,比如所有的自然数。使用列表永远不可能存储所有自然数。6.小结所有可以在for循环中使用的对象都是Iterable类型;next()函数中可以使用的所有对象都是Iterator类型,代表一系列惰性计算;list、dict、str等集合数据类型是Iterable不是Iterator,而是可以通过iter()函数得到一个Iterator对象。Python的for循环本质上就是通过不断调用next()函数来forxin[1,2,3,4,5]:pass其实完全等价于:#首先获取Iterator对象:it=iter([1,2,3,4,5])#Loop:whileTrue:try:#获取下一个值:x=next(it)exceptStopIteration:#当遇到StopIteration时退出循环break