1. 生成器

2. 创建生成器方法1

3. 创建生成器方法2

4. 使用send唤醒

生成器

2. 创建生成器方法1

``````
In [15]: L = [ x*2 for x in range(5)]

In [16]: L
Out[16]: [0, 2, 4, 6, 8]

In [17]: G = ( x*2 for x in range(5))

In [18]: G
Out[18]:  at 0x7f626c132db0>

In [19]:
``````

``````
In [19]: next(G)
Out[19]: 0

In [20]: next(G)
Out[20]: 2

In [21]: next(G)
Out[21]: 4

In [22]: next(G)
Out[22]: 6

In [23]: next(G)
Out[23]: 8

In [24]: next(G)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
in ()
----> 1 next(G)

StopIteration:

In [25]:
``````
``````In [26]: G = ( x*2 for x in range(5))

In [27]: for x in G:
....:     print(x)
....:
0
2
4
6
8

In [28]:
``````

3. 创建生成器方法2

generator非常强大。如果推算的算法比较复杂，用类似列表生成式的 for 循环无法实现的时候，还可以用函数来实现。

``````class FibIterator(object):
"""斐波那契数列迭代器"""
def __init__(self, n):
"""
:param n: int, 指明生成数列的前n个数
"""
self.n = n
# current用来保存当前生成到数列中的第几个数了
self.current = 0
# num1用来保存前前一个数，初始值为数列中的第一个数0
self.num1 = 0
# num2用来保存前一个数，初始值为数列中的第二个数1
self.num2 = 1

def __next__(self):
"""被next()函数调用来获取下一个数"""
if self.current < self.n:
num = self.num1
self.num1, self.num2 = self.num2, self.num1+self.num2
self.current += 1
return num
else:
raise StopIteration

def __iter__(self):
"""迭代器的__iter__返回自身即可"""
return self
``````

``````
In [30]: def fib(n):
....:     current = 0
....:     num1, num2 = 0, 1
....:     while current < n:
....:         num = num1
....:         num1, num2 = num2, num1+num2
....:         current += 1
....:         yield num
....:     return 'done'
....:

In [31]: F = fib(5)

In [32]: next(F)
Out[32]: 1

In [33]: next(F)
Out[33]: 1

In [34]: next(F)
Out[34]: 2

In [35]: next(F)
Out[35]: 3

In [36]: next(F)
Out[36]: 5

In [37]: next(F)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
in ()
----> 1 next(F)

StopIteration: done
``````
``````def create_num(all_num):
print("----1---")   # 其它的语言也一样，都可以通过打印结果来调试函数
# a = 0
# b = 1
a, b = 0, 1
current_num = 0
while current_num < all_num:
print("----2---")
# print(a)
yield a  # 如果一个函数中有yield语句，那么这个就不在是函数，而是一个生成器的模板
print("----3---")
a, b = b, a+b
current_num += 1
print("----4---")

# 如果在调用create_num的时候，发现这个函数中有yield那么此时，不是调用函数，而是创建一个生成器对象
obj = create_num(10)

ret = next(obj)
print(ret)

ret = next(obj)
print(ret)

obj2 = create_num(2)

ret = next(obj2)
print(ret)

# for num in obj:
#    print(num)

``````

``````
In [38]: for n in fib(5):
....:     print(n)
....:
1
1
2
3
5

In [39]:
``````

``````In [39]: g = fib(5)

In [40]: while True:
....:     try:
....:         x = next(g)
....:         print("value:%d"%x)
....:     except StopIteration as e:
....:         print("生成器返回值:%s"%e.value)
....:         break
....:
value:1
value:1
value:2
value:3
value:5

In [41]:
``````

``````def create_num(all_num):
# a = 0
# b = 1
a, b = 0, 1
current_num = 0
while current_num < all_num:
# print(a)
yield a  # 如果一个函数中有yield语句，那么这个就不在是函数，而是一个生成器的模板
a, b = b, a+b
current_num += 1
return "ok...."

obj2 = create_num(50)

while True:
try:
ret = next(obj2)
print(ret)
except Exception as ret:
print(ret.value)
break``````

总结

• 使用了yield关键字的函数不再是函数，而是生成器。（使用了yield的函数就是生成器）
• yield关键字有两点作用：
• 保存当前运行状态（断点），然后暂停执行，即将生成器（函数）挂起
• 将yield关键字后面表达式的值作为返回值返回，此时可以理解为起到了return的作用
• 可以使用next()函数让生成器从断点处继续执行，即唤醒生成器（函数）
• Python3中的生成器可以使用return返回最终运行的返回值，而Python2中的生成器不允许使用return返回一个返回值（即可以使用return从生成器中退出，但return后不能有任何表达式）。

4. 使用send唤醒

``````In [10]: def gen():
....:     i = 0
....:     while i<5:
....:         temp = yield i
....:         print(temp)
....:         i+=1
....:
``````

``````
In [43]: f = gen()

In [44]: next(f)
Out[44]: 0

In [45]: f.send('haha')
haha
Out[45]: 1

In [46]: next(f)
None
Out[46]: 2

In [47]: f.send('haha')
haha
Out[47]: 3

In [48]:
``````

send和next区别时两者的的返回值都是yield a

``````In [11]: f = gen()

In [12]: next(f)
Out[12]: 0

In [13]: next(f)
None
Out[13]: 1

In [14]: next(f)
None
Out[14]: 2

In [15]: next(f)
None
Out[15]: 3

In [16]: next(f)
None
Out[16]: 4

In [17]: next(f)
None
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
in ()
----> 1 next(f)

StopIteration:
``````

``````In [18]: f = gen()

In [19]: f.__next__()
Out[19]: 0

In [20]: f.__next__()
None
Out[20]: 1

In [21]: f.__next__()
None
Out[21]: 2

In [22]: f.__next__()
None
Out[22]: 3

In [23]: f.__next__()
None
Out[23]: 4

In [24]: f.__next__()
None
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
in ()
----> 1 f.__next__()

StopIteration:``````