什么是生成器?
生成器是一次生成一个值得特殊类型函数。函数在执行的过程中,yield语句会把你需要的值返回给next函数调用的地方,然后退出函数,再次使用next语句调用的时候,又从上次中断的地方开始执行,而生成器的所有变量参数都会保存下来供下一次使用。
大多数时候生长期是以函数来实现的,然而,他们并不返回一个值,而是yield“生出”一个值。
# 使用生成器
>>> def MyYield():
... print("生出一个值为:")
... yield 1
... yield 2
...
>>> my = MyYield()
>>> next(my)
生出一个值为:
1
>>> next(my)
2
>>> next(my)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
# 使用for语句
>>> for i in my:
... print(i)
...
>>> my = MyYield()
>>> for i in my:
... print(i)
...
生出一个值为:
1
2
>>>
# 使用生成器实现斐波那契数列
>>> def fibs():
... a = 0
... b = 1
... while True:
... a,b = b,a+b
... yield a
...
>>> fi = fibs()
>>> for i in fi:
... if i>100:
... break
... print(i,end=' ')
...
1 1 2 3 5 8 13 21 34 55 89 >>>
>>>
生成器的创造方法
通过列表生成式,我们可以直接创建一个列表,但是,由于内存有限,那么就无法实现列表的创建。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素,从而节省时间和空间,这种一边循环一边计算的机制,成为生成器(Generator)。
#列表生成式推导过程
>>> mylist = []
>>> for x in range(10):
... mylist.append(x)
...
>>> mylist
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
#列表生成式实现过程
>>> newlist = [x for x in range(10)]
>>> newlist
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>
#将列表生成式的[]改成(),就创建了一个生成器
>>> myyield = (x for x in range(10))
>>> myyield
<generator object <genexpr> at 0x101ce5c50>
>>> next(myyield)
0
>>> next(myyield)
1
>>> next(myyield)
2
>>> for x in myyield:
... print(x)
...
3
4
5
6
7
8
9
>>>
# 利用生成器实现斐波那契数列
>>> def fibs(max):
... a = 0
... b = 1
... n = 0
... while n<max:
... a,b = b,a+b
... yield a
... n +=1
...
>>> fi = fibs(10)
>>> fi
<generator object fibs at 0x101ce5ba0>
# 使用内置的next()函数获取元素
>>> next(fi)
1
>>> next(fi)
1
>>> next(fi)
2
# 剩下的可以使用for语句遍历出来
>>> for i in fi:
... print(i)
...
3
5
8
13
21
34
55
>>>
#或者将生成器对象转换为元祖
>>> fi = fibs(10)
>>> fi
<generator object fibs at 0x101ce5ba0>
>>> tuple(fi)
(1, 1, 2, 3, 5, 8, 13, 21, 34, 55)
>>>
#或者使用内置的__next__()方法获取下一个元素
>>> fi = fibs(10)
>>> fi
<generator object fibs at 0x101ce5ca8>
>>> fi.__next__()
1
>>> fi.__next__()
1
>>> fi.__next__()
2
>>>
# 斐波那契数列中10000到50000之间的数
>>> fi = fibs(100000)
>>> for i in fi:
... if i>10000 and i<50000:
... print(i)
... break
...
10946
>>>