跟着菜鸟教程初学python3,在"迭代器与生成器"一节,遇到个比较生疏的概念“生成器”,下面贴一下我的理解,如有不对之处,请多多指正:
所谓生成器,就是代码中使用到了yield关键字的函数
普通的函数,返回值类型根据return的类型而定,
而这样的函数,返回值类型固定为迭代器类型<class 'generator'>
与return相比,yield起到的效果是“记忆返回”:
像所有的迭代器一样,第一次调用迭代器对象的__next__()方法时,
才真正从开始处执行函数体,并在遇到yield时返回其后的值,
并且它能记住此次返回的位置及上下文,下次再调用__next__()方法时,
从上次返回的位置处继续往下执行,直到再次遇到yield,
如此循环,直到函数体彻底执行完毕,并产生StopIteration异常,
迭代器的调用者通常应该识别该异常。
深入理解:
应该结合函数对象的概念进行理解:
函数名指代的就是该函数对象
函数名(),是执行的"函数对象"的"括号运算"方法
对普通的"函数对象"而言,"括号运算"方法,就是执行函数体
"括号运算"的返回类型依据return的数据而定
而对于生成器类函数对象,其"括号运算"方法返回的类型为 generator 类型
(generator类型为Iterator的派生类型)
而该迭代器类型负责"把控"函数体的执行:
它可以维护当前函数体的执行位置和上下文
它的__next__()成员方法负责从上次记忆位置执行函数体
__next__()每次返回的数据类型,由本次遇到yield时其后的类型而定
举例:
>>> def func3():
... print("---1---") #函数体第1句
... yield 1 #函数体第2句
... print("---a---") #函数体第3句
... yield "a" #函数体第4句
... print("---[1,2]---") #函数体第5句
... yield [1,2] #函数体第6句
... print("---finish---") #函数体第7句
...
>>> f3=func3() #这里得到的f3固定为迭代器对象
>>> type(f3)
<class 'generator'>
>>> from collections import Iterable,Iterator
>>> print(isinstance(f3,Iterator))
True #表明返回的是迭代器类型,亦即支持__next__()方法
>>> r1=next(f3) #第一次调用next(),从函数体开始处执行,执行完函数体第2句后返回
---1--- #函数体第1句执行的结果
>>> type(r1) #r1存放的是 yield 1 返回的结果,整数型
<class 'int'>
>>> r2=f3.__next__()#再调用next(),从上次位置(函数体的第3句)执行,执行完函数体第4句后返回
---a--- #函数体第3句执行的结果
>>> type(r2) #r2存放的是 yield "a" 返回的结果,字符串型
<class 'str'>
>>> r3=next(f3) #再调用next(),从上次位置(函数体的第5句)执行,执行完函数体第6句后返回
---[1,2]--- #函数体第5句执行的结果
>>> type(r3) #r3存放的是 yield [1,2] 返回的结果,列表型
<class 'list'>
>>> r4=next(f3) #再调用next(),从上次位置(函数体的第7句)执行,执行完后发出异常
---finish--- #函数体第7句执行的结果
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
|