yield

yield,可以看为return,但是返回的不是一个函数的输出,是一个生成器的结果。当程序遇到yield后,停止执行并返回,当再次调用时,会在停止的地方继续执行。一个方法用来yield,那么它就是一个生成器。

注意:

  • 必须要启动一次next(func),才能seed非空值,否则只能seed(None)
  • seed(None),相当于next(func)

    举例1:

    ```python def fun(): print(“函数开始”) while True:
    1. result = yield 1
    2. print("result:{}".format(result))
    run = fun() print(next(run)) print(“———————————“) print(next(run)) ‘’’ 函数开始 1

result:None 1 ‘’’ ‘’’ 流程: 1.run = fun(),得到生成器run 2.调用next方法,fun函数开始执行,先print方法,然后进入while循环 3.遇到yield,然后把yield想成return,return了一个1之后,程序停止,需要注意:此时并没有执行赋值给result操作 4.执行print(“———————————“) 5.再次调用next方法,此时从上次停止的地方执行,也就是给result赋值,但是由于右边已经return出去了,同时也没传参数, 所以result是空的(None) 6.print(“result:{}”.format(result)) 7.进入while True,遇到yield,也就是return了一个1之后,程序停止。 ‘’’

  1. <a name="tFz9p"></a>
  2. ### 举例2:
  3. ```python
  4. def fun():
  5. print("函数开始")
  6. while True:
  7. result = yield 1
  8. print("result:{}".format(result))
  9. run = fun()
  10. print(next(run))
  11. print("----------------------")
  12. print(run.send(2))
  13. '''
  14. 函数开始
  15. 1
  16. ----------------------
  17. result:2
  18. 1
  19. '''
  20. '''
  21. 流程:
  22. 1.run = fun(),得到生成器run
  23. 2.调用next方法,fun函数开始执行,先print方法,然后进入while循环
  24. 3.遇到yield,然后把yield想成return,return了一个1之后,程序停止,需要注意:此时并没有执行赋值给result操作
  25. 4.执行print("----------------------")
  26. 5.执行run.send(2)方法,此时从上次停止的地方执行,也就是给result赋值,send(2)也就是result=2
  27. 6.print("result:{}".format(result)),注意此时的result=2
  28. 7.进入while True,遇到yield,也就是return了一个1之后,程序停止。
  29. '''

斐波拉契队列:

  1. def run(n):
  2. a,b,c=0,1,1
  3. while True:
  4. if c > n:
  5. return
  6. else:
  7. yield a
  8. a,b=b,a+b
  9. c+=1
  10. a=run(10) //拿到生成器a
  11. for i in a: //通过遍历的方式调用
  12. print(i,end='\t')
  13. #list(a) #通过list转换直接调用
  14. '''
  15. 0 1 1 2 3 5 8 13 21 34
  16. '''

生产者与消费者

  1. import time
  2. def consumer():
  3. r = ''
  4. while True:
  5. n = yield r
  6. if not n:
  7. return
  8. print('[CONSUMER] Consuming %s...' % n)
  9. time.sleep(1)
  10. r = '200 OK'
  11. def produce(c):
  12. next(c)
  13. n = 0
  14. while n < 5:
  15. n = n + 1
  16. print('[PRODUCER] Producing %s...' % n)
  17. r = c.send(n)
  18. print('[PRODUCER] Consumer return: %s' % r)
  19. c.close()
  20. if __name__=='__main__':
  21. c = consumer()
  22. produce(c)

close方法

  1. def func():
  2. one=yield '第一行'
  3. yield '第二行'
  4. yield '第三行'
  5. f=func()
  6. # print(f.send('111')) 报错,因为还没开启生成器
  7. print(next(f))#第一行
  8. print(next(f))#第二行
  9. f.close()#关闭生成器
  10. print(next(f)) #StopIteration报错,因为已经关闭了生成器

throw方法

  1. def func():
  2. try:
  3. yield '第一行'
  4. except Exception:
  5. pass
  6. yield '第二行'
  7. yield '第三行'
  8. f=func()
  9. next(f)#第一行
  10. #需要注意的是f.throw也相当于一次next,它是有返回值的,这里的返回值是'第二行'
  11. f.throw(Exception,'error!!!')#自己给自己抛异常并捕获
  12. next(f) #第三行

yield from

  1. def fun1(arg):
  2. yield arg
  3. def fun2(arg):
  4. yield from arg
  5. for i in fun1(range(10)):
  6. print(i)
  7. '''
  8. range(10)
  9. '''
  10. for i in fun2(range(10)):
  11. print(i,end='\t')
  12. '''
  13. 0 1 2 3 4 5 6 7 8 9
  14. '''
  • 这说明yield就是将range这个可迭代对象直接返回了
  • 而yield from解析了range对象,将其中每一个item返回了
  • yield from iterable本质上等于for item in iterable: yield item的缩写版 ,也就是说:yield from后面必须跟iterable对象

    Async/Await

    定义异步函数

    1. async def async_function():
    2. pass
    协程需要驱动才能运行,直接使用send(None)
    1. print(async_function().send(None)) >>> StopIteration: 1
    因为生成器/协程在正常返回退出时会抛出一个StopIteration异常,而原来的返回值会存放在StopIteration对象的value属性中,通过以下捕获可以获取协程真正的返回值:
    1. try:
    2. async_function().send(None)
    3. except StopIteration as e:
    4. print(e.value)

    await

    在协程函数中,可以通过await语法来挂起自身的协程,并等待另一个协程完成直到返回结果
    注意并非是异步处理的,注意挂起这个词 ```python async def async_function(): return 1

async def await_coroutine(): result = await async_function() return result

try: await_coroutine().send(None) except StopIteration as e: print(e.value) >>>1 ```

  • 要注意的是,await语法只能出现在通过async修饰的函数中,否则会报SyntaxError错误。
  • 而且await后面的对象需要是一个Awaitable,或者实现了相关的协议