# 生成器进化到协程 Part 1

Rookie

## 生成器（generator）

``````def countdown(n):
while n > 0:
yield n
n -= 1

c = countdown(10)
c``````
``<generator object countdown at 0x0000021F5EAB9F10>``

``````for x in countdown(10):
print('倒数：', x)``````
``````倒数： 10

``````c = countdown(3)

# next(c)
3
# next(c)
2
# next(c)
1``````

## 把生成器当作管道

``````def add_A(seq):
for item in seq:
yield item + '-A'

for item in seq:
yield item + '-B'

for item in seq:
yield item + '-C'

seq = ['apple', 'banana', 'orange']

for item in stacked_generator:
print(item)``````
``````apple-A-B-C
banana-A-B-C
orange-A-B-C``````

## yield 可以接受传值

`yield` 的作用是向调用者返回一个值，调用者其实也可以向生成器传值。

``````def receiver():
while True:

def caller():
next(recv) # 使生成器前进到 yield
for i in 'abcd':
recv.send(i)

caller()``````
``````收到： a

`send` 函数的返回值是什么呢？

``````def receiver():
call_times = 0
while True:
item = yield call_times
print('收到：', item)
call_times += 1

def caller():
next(recv)
for i in 'abcd':
ret_value = recv.send(i)
print('返回值: ', ret_value)

caller()``````
``````收到： a

## 生成器 101

• `yield` 用于定义生成器函数
• 只要 `yield` 存在该函数必定是一个生成器
• 调用该函数返回一个生成器

### 让一个生成器前进

``````def generator():
yield 'a'
yield 'b'

gen = generator()

# next(gen)
'a'
# next(gen)
'b'``````

### 给生成器传值

``````def generator():
item = yield 'a'
print(item)
another_item = yield 'b'

gen = generator()
print(next(gen))
print(gen.send(1))``````
``````a
1
b``````

### 关闭一个生成器

``````def generator():
times = 0
while True:
yield times
times += 1

gen = generator()
print(next(gen))
print(next(gen))
gen.close() # 不会抛出错误``````
``````0
1``````

### 抛出错误

`throw` 的函数签名如下：

``throw(typ, [,val, [,tb]])``

``````def generator():
try:
yield 'apple'
except RuntimeError as e:
print('捕捉到：', e)
yield 'banana'

gen = generator()
print(next(gen))
print(gen.throw(RuntimeError, '运行错误'))``````
``````apple

banana``````

### 生成器返回值

``````def generator():
yield
return 'apple'

g = generator()
next(g)
try:
next(g)
except StopIteration as e:
print(e)``````
``apple``

### 生成器委托

``````def generator():
yield 'a'
yield 'b'
return 'c'

def func():
result = yield from generator()
print(result)``````

``````# func()
<generator object func at 0x0000021F5EB0F990>

# next(func())
'a'``````

``````def chain(x, y):
yield from x
yield from y

a = [1, 2, 3]
b = [4, 5, 6]

for i in chain(a, b):
print(i, end=' ')``````
``1 2 3 4 5 6 ``
``````c = [7, 8, 9]
for i in chain(a, chain(b, c)):
print(i, end=' ')``````
``1 2 3 4 5 6 7 8 9 ``

## Part 1总结

### 生成器定义

``````def generator():
...
yield
...
return result``````

### 生成器操作

``````gen = generator()

# 使一个生成器前进
next(gen)

# 传递一个值
gen.send(item)

# 中止生成器
gen.close()

# 抛出错误
gen.throw(exc, val, tb)

# 委托
result = yield from gen``````

26 声望
3 粉丝
0 条评论