浅析python中生成器generator

青春壹個敷衍的年華 提交于 2019-12-16 23:20:05

生成器是什么?

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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!