13.python |
您所在的位置:网站首页 › python里的迭代器 › 13.python |
python-yield和yield from
目录python-yield和yield from可迭代、迭代器、生成器yield关键字生成器的执行状态yield from参考资料
1:可迭代、迭代器、生成器
2:如何运行/激活生成器
3:生成器的执行状态
4:从生成器过渡到协程:yield
可迭代、迭代器、生成器
from collections.abc import Iterable, Iterator, Generator
isinstance(obj, Iterable) # 可迭代对象
isinstance(obj, Iterator) # 迭代器
isinstance(obj, Generator) # 生成器
Iterable:可迭代对象,一般在python中想字符串,list, dict, tuple, set, deque等都是可迭代对象,一个对象只要实现了__iter__ 方法的,均可称为可迭代对象。 Iterator:迭代器,一般对象只要实现了__next__ 与 __iter__ 方法的均可称为迭代器。 Generator:生成器,是在迭代器的基础上(可以用for循环,可以使用next()),再实现了yield。 yield相当于我们函数里的return。在每次next(),或者for遍历的时候,都会yield这里将新的值返回回去,并在这里阻塞,等待下一次的调用。 可迭代象和迭代器,是将所有的值都生成存放在内存中,而生成器则是需要元素才临时生成,节省时间,节省空间。 yield关键字yield的用法很像return,都是提供一个返回值,但是yield和return的最大区别在于,return一旦返回,则代码段执行结束,但是yield在返回值以后,会交出CUP的使用权,代码段并没有直接结束,而是在此处中断,当调用send()或者next()方法之后,yield可以从之前中断的地方继续执行。 在一个函数中,使用yield关键字,则当前的函数会变成生成器。 def fib(n): index = 0 a = 0 b = 1 while index < n: yield b a,b = b, a+b index += 1 fib = fib(100) print(fib) print(next(fib)) print(next(fib)) print(next(fib)) print(next(fib)) 1 1 2 3使用next 在生成器为空的时候会报错StopIteration,使用for 循环可以避免为空的错误 def fib(n): index = 0 a = 0 b = 1 while index < n: yield b a,b = b, a+b index += 1 fib = fib(3) print(next(fib)) print(next(fib)) print(next(fib)) print(next(fib)) print(next(fib)) 1 1 2 StopIteration def fib(n): index = 0 a = 0 b = 1 while index < n: yield b a,b = b, a+b index += 1 fib = fib(3) for i in fib: print(i) 1 1 2使用send()方法允许我们向生成器中传值。 import time def fib(n): index = 0 a = 0 b = 1 while index < n: sleep = yield b print(f'等待{sleep}秒,设置n={n}') time.sleep(sleep) a,b = b, a+b index += 1 fib = fib(20) print(fib.send(None)) # 效果等同于print(next(fib)) print(fib.send(1)) print(fib.send(2)) print(fib.send(3)) print(fib.send(4))调用fib.send(None)方法,此处作用与next(fib)相同,程序返回当前b的值1, 程序中断。 调用fib.send(2)方法,程序被唤醒,将2传递给yield之前的变量sleep,程序继续运行,直到遇到yield将新的b返回,程序再次中断 如此继续下去,直到程序结束。 生成器的执行状态GEN_CREATED 等待开始执行 GEN_RUNNING 解释器正在执行(只有在多线程应用中才能看到这个状态) GEN_SUSPENDED 在yield表达式处暂停 GEN_CLOSED 执行结束 def simple_coro(a): print('-> Started: a=',a) b = yield a # 相当于是先返回a,暂停,直到next方法调用后,b赋值为send发送过来的数据,再执行到下一个yield暂停 print('-> Received: b =',b) c = yield a+b # 先返回a+b,暂停,直到next方法调用后,c赋值为send发送过来的数据,再执行到下一个yield暂停 print('-> Received: c=',c) my_coro2=simple_coro(14) # 实例化一个协程对象 from inspect import getgeneratorstate # 得到状态的函数 print(getgeneratorstate(my_coro2)) next(my_coro2) print(getgeneratorstate(my_coro2)) my_coro2.send(28) my_coro2.send(99) print(getgeneratorstate(my_coro2)) GEN_CREATED -> Started: a= 14 GEN_SUSPENDED -> Received: b = 28 -> Received: c= 99 Traceback (most recent call last): File "d:/TzxNote/Note/lcodeNoteCards/testpy.py", line 15, in my_coro2.send(99) StopIteration yield fromyield from 所在的函数被称为委托生成器,它主要为调用方和子生成器提供一个双向通道 yield from 后面需要加的是可迭代对象,它可以是普通的可迭代对象,也可以是迭代器,甚至是生成器。 代替内层for循环 def generator(): for i in range(10): yield i def generator2(): yield from range(10)链接子生成器 def generator1(): item = range(3) for i in item: yield i def generator2(): yield 'a' yield 'b' yield from generator1() # yield from iterable本质上等于 for item in iterable: yield item的缩写版 yield from [11, 22, 33, 44] yield from range(5,10) for i in generator2(): print(i) a b 0 1 2 11 22 33 44 5 6 7 8 9 参考资料https://www.cnblogs.com/cnkai/p/7514828.html http://events.jianshu.io/p/dda2003e1aa2 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |