生成器generator
看到生成器,最先想到yield关键字,generator object
1,用于协程,最近(2023/6/1)开始看到生成器用于协程这方面的内容,但还没接触,开始有所了解。
.send方法
如果列表元素可以按照某种算法推算出来,那我们因此可以在循环的过程中不断推算出后续的元素,这样就不必创建完整的list,从而节省大量的空间。
在Python中,这种一边循环一边计算的机制,称为生成器:generator。
generator保存的是算法,每次调用next( g ),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。
创建生成器的2种方式:
1,把列表生成式中的中括号[ ] 改成小括号( )
2,生成器函数——yield关键字:如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。
使用生成器:
我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它(因为如果生成器对象很多,使用next( )函数来获取每一个元素,会很麻烦),并且不需要关心StopIteration的错误。(是因为for循环内部会处理异常)
对于函数改成的generator来说,遇到return语句或者执行到函数体最后一行语句,就是结束generator的指令,for循环随之结束。
执行流程:
最难理解的就是generator和函数的执行流程不一样。
函数:是顺序执行,遇到return语句或者最后一行函数语句就返回。
generator函数:在每次调用next( )的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
生成器拿不到return语句的返回值
用for循环调用generator时拿不到return语句的返回值。
如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中。
1 #定义一个生成器函数 2 def odd(): 3 print('step 1') 4 yield 1 5 print('step 2') 6 yield(3) 7 print('step 3') 8 yield(5) 9 10 11 print("\n以下调用方式会创建多个独立的生成器:") 12 print(next(odd())) 13 print(next(odd())) 14 print(next(odd())) 15 16 17 print('\n正确的调用方式:') 18 g = odd() 19 print(next(g)) 20 print(next(g)) 21 print(next(g)) 22 print(next(g))
调用该generator函数时,首先要生成一个generator对象,然后用next()函数不断获得下一个返回值,当迭代完再使用next()函数时会报错StopIteration。
调用generator函数会创建一个generator对象,多次调用generator函数会创建多个相互独立的generator。
另外一个小众的使用场景,是变相实现协程的效果,即在同一个线程内,实现不同任务交替执行。
下面这部分代码能快速理解为什么说不同任务交替执行。
def mytask1(): print('task1 开始执行') ''' task code ''' yield def mytask2(): print('task2 开始执行') ''' task code ''' yield gene1=mytask1() gene2=mytask2() for i in range(100): next(gene1) next(gene2)
yield 在返回值以后,会交出 CPU 的使用权,代码段并没有直接结束,而是在此处中断,当调用 send() 或者 next() 方法之后,yield 可以从之前中断的地方继续执行。

浙公网安备 33010602011771号