13.python

您所在的位置:网站首页 python里的迭代器 13.python

13.python

2023-05-27 13:38| 来源: 网络整理| 查看: 265

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 from

yield 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