Python的生成器和迭代器,Python的生成器和迭代器对于喜欢Python开发的小伙伴应该不陌生,不懂也没关系。这篇文章就为小伙伴们详细讲解一下Python的生成器和迭代器,有兴趣的可以关注小编了解更多。列表生成公式:例1:a=[i+1foriinrange(10)]print(a)输出:[1,2,3,4,5,6,7,8,9,10]例2:L=[1,2,3,4,5]print([i*iforiinLifi>3])输出:[16,25]示例3:L=[1,2,3,4,5]I=[6,7,8,9,10]print([i*aforiinLforainIifi>2ifa<8])输出:[18,21,24,28,30,35]生成器:通过列表理解,我们可以直接创建一个列表。但是,由于内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用大量存储空间,而且如果我们只需要访问前几个元素,后面的大部分元素占用的空间都会被浪费掉。因此,如果列表元素可以根据某种算法计算出来,那么就不需要创建一个完整的列表,从而节省了大量的空间。在Python中,这种while循环计算的机制被称为生成器:generator。创建生成器的方法有很多种。第一种方法很简单,只要把一个列表生成的[]改成(),就创建了一个生成器:例子:L=[1,2,3,4,5]I=[6,7,8,9,10]g=(i*aforiinLforainI)print(g)output:at0x00000276586C1F48>创建L和g的区别只是最外层的[]和(),L是列表,g是生成器。我们可以通过generator的next()方法next(g)直接打印出列表的每一个元素。示例1:L=[1,2,3,4,5]I=[6,7,8,9,10]g=(i*aforiinLforainI)print(next(g))print(next(g))print(next(g))输出:678示例2:L=[1,2,3,4,5]I=[6,7,8,9,10]g=(i*aforiinLforainIifi>2ifa<8)print(next(g))print(next(g))print(next(g))output:182124因为生成器保存了算法,每次调用next(g)都会计算g的下一个元素的值,直到计算完最后一个元素,没有更多元素时,抛出StopIteration错误。正确的方法是使用for循环,因为生成器也是可迭代对象:示例3:g=(i*iforiinrange(0,5))foriing:print(i)在我们创建生成器之后,基本上从不调用next()方法,而是通过for循环对其进行迭代。发电机非常强大。如果计算算法比较复杂,不能用类似列表生成的for循环实现,也可以用函数实现。比如著名的斐波那契数列(Fibonacci),除了第一个和第二个数外,任何数都可以通过前两个数相加得到:1,1,2,3,5,8,13,21,34,...斐波那契数列不能用列表理解来写,但很容易用函数打印它:deffib(max):n,a,b=0,0,1whilen调用方法:##但是在使用for循环调用生成器的时候,\##发现不能得到生成器的return语句\##返回值。如果要获取返回值,必须捕获StopIteration错误,返回值包含在StopIteration的值中:foriinfib(5):print(i)output:11235or:date=fib(5)print(date.__next__())print(date.__next__())print(date.__next__())print('test')print(date.__next__())print(date.__next__())输出:112test35send方法有一个参数,该参数指定了上一次挂起的yield语句的返回值。在单线程的情况下也可以通过yield实现并发操作的效果。coding:utf-8author='AlexLi'importtimedefconsumer(name):print("%s可以吃包子了!"%name)whileTrue:baozi=yieldprint("包子[%s]来了,被吃掉了by[%s]!"%(baozi,name))defproducer(name):c=consumer('A')c2=consumer('B')c.__next__()c2.__next__()print("I我准备做包子了!”)foriinrange(10):time.sleep(1)print("我做了2个包子!")c.send(i)c2.send(i)producer("alex")通过生成器实现协程并行运行迭代器:可以直接作用于for循环的数据类型有:一种是集合数据类型,如list、tuple、dict、set、str等;另一个是generator,包括generator和generatorfunctionwithyield。这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。您可以使用isinstance()来确定一个对象是否是一个可迭代对象:10)),Iterable)Trueisinstance(100,Iterable)False生成器不仅可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示不能返回下一个值。*能被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。您可以使用isinstance()来确定对象是否是Iterator对象:fromcollectionsimportIteratorisinstance((xforxinrange(10)),Iterator)Trueisinstance([],Iterator)Falseisinstance({},Iterator)Falseisinstance('abc',Iterator)False生成器都是Iterator对象,但是list、dict、str虽然是Iterable,但不是Iterator。将list、dict、str等Iterable变为Iterator,可以使用iter()函数:isinstance(iter([]),Iterator)Trueisinstance(iter('abc'),Iterator)Truewhylist,dict,str等数据类型不是Iterator吗?这是因为Python的Iterator对象代表一个数据流,Iterator对象可以被next()函数调用,不断返回下一条数据,直到没有数据时抛出StopIteration错误。这个数据流可以看作是一个有序的序列,但是我们无法预先知道序列的长度,只能通过next()函数不断的按需计算下一个数据,所以Iterator的计算是惰性的,只当需要时,只会在下一个数据返回时才计算。迭代器甚至可以表示无限的数据流,比如所有的自然数。使用列表永远不可能存储所有自然数。总结:所有可以应用到for循环的对象都是Iterable类型;所有可以应用于next()函数的对象都是Iterator类型,代表一系列惰性计算;list、dict、str等集合数据类型是Iterable但不是Iterator,而是可以通过iter()函数得到一个Iterator对象。Python3的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