生成器是什么?
Python中,“万物皆对象”,生成器也是一种对象,该对象含有__iter__(),next()方法,也可被代入iter(),next()方法。当被代入iter()方法,返回一个迭代器(也是一种对象),而生成器本身就是迭代器,即iter(object) is object 的结果为True。
怎么产生生成器?
生成器对象可以通过生成器函数及生成器表达式产生,产生后自动有__next__(),iter()方法,及可被iter(),next()调用。
生成器函数
这种方法就是在def函数中,使用yield语句:
>>>def gen(N):
yield N
>>> p=gen(10)
>>> type(p)
<class 'generator'>
>>> dir(p)
['__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__name__', '__ne__', '__new__', '__next__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw']
>>> p=test1(4)
>>> p is iter(p)
True
表明p就是一个生成器,也验证了p is iter§ 的结果是True,即生成器本身就是迭代器。
生成器表达式
生成器表达式就是在()中的推导表达式:
>>> t=(i for i in range(4))
>>> type(t)
<class 'generator'>
表明t就是一个生成器。
生成器如何工作的?
生成一个生成器后,在迭代环境下(for ,while,list等语句)下,程序自动调用生成器的__next__()方法,等效于next(generator)方法,这就为我们人工检测它的工作原理提供了可能:
>>> def test1(N):
print('begin...')
for i in range(N):
print('start?...')
yield i
print('end?...')
>>> p=test1(4)
>>> next(p)
begin...
start?...
0
>>> next(p)
end?...
start?...
1
>>> next(p)
end?...
start?...
2
>>> q=test1(4)
>>> next(q)
begin...
start?...
0
>>> next(p)
end?...
start?...
3
>>> next(p)
end?...
Traceback (most recent call last):
File "<pyshell#33>", line 1, in <module>
next(p)
StopIteration
通过上例,可以看出,当被next调用时,test1函数先执行到yield语句处,提供一个返回值,然后记住该处位置,再次被next调用,再往下执行,再执行到yield语句处,提供一个返回值,然后记住该处位置,直到把所有值返回完毕,抛出StopIteration异常。
值得注意的是,不同于其他序列对象,生成器是单迭代对象,即iter()后产生的迭代器是同一个对象,所以有:
>>> p=(i+1 for i in range(4))
>>> d=iter(p)
>>> e=iter(p)
>>> next(d)
1
>>> next(e)
2
>>> d is e
True
与之形成对比的,比如list对象,有:
>>> a=[1,2,3,4]
>>> b=iter(a)
>>> c=iter(a)
>>> next(b)
1
>>> next(b)
2
>>> next(c)
1
>>> b is c
False
生成器的send()用法
generator.send(value)方法,可以与程序内的x=yield item进行交互,即将value赋予了x,如果没有被赋予值,则x为None,如下例:
>>> def test2(N): for i in range(N): print('start...') x=yield i print(x) print('end...')
>>> p=test2(4)
>>> next(p)
start...
0
>>> next(p)
None
end...
start...
1
>>> p.send(100)
100
end...
start...
2
>>> p.send(78)
78
end...
start...
3
>>> next(p)
None
end...
Traceback (most recent call last):
File "<pyshell#77>", line 1, in <module>
next(p)
StopIteration
来源:CSDN
作者:YJW1227
链接:https://blog.csdn.net/YJW1227/article/details/103570920