關於 python 中 yield 的記錄


yield (生成器)好似是個比較難理解的概念.
當這個生成器被執行時.將會回傳一個 itertor.
之後便可以通過 next() 或者是 send(something) 來呼叫
而他執行後會記住上一次的執行結果..之後再繼續執行

記錄一下測試的東西.希望可以在將來使用吧.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
def test():
print '1'

x = yield '2'
print 'x = %s' % x

y = 100 + (yield x)
print 'y = %s' % y

# 產生一個變數以作儲存生成器
test = test()

# 之後他會執行到 yield 那一行便暫停,並回傳結果
test.next()
> 1
> '2'

# 接著再通過 send(something)/next 函數再繼續執行到下一個 yield 便再暫停與回傳
# 而當送出 200 時, test() 函數的 x 便會改變為 200,所以便出現了下面的結果
test.send(200)
> x=200
> 200

# 最後同上,當送出 999 時.便會自動執行暫停行數 y = 100 + (yield x)
# yield x 便會自動改變為 999. 所以計算後出現了此結果
# 但是當後面已經沒有 yield 時.便會掉出例外事件
test.send(999)
> y=1099
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> StopIteration
</module></stdin>

看一下其他例子 (在一開始時.並需要使用 next(),而不能直接 send)
再者每一個 yield 通常都會承接上一次的 yield,即 y 會承接 x (因為是 itertor)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def test2():
t = 'Startup'
x = yield t
y = yield x
z = yield y

test2 = test2()

test2.next()
> 'Startup'

test2.send(2)
> 2

test2.send(3)
> 3

最後一個例子.
其實就是將整倨 list 放進函數中.之後直接改變其內在的值

1
2
3
4
5
6
7
8
def to_chr(y):
for i in y:
i = chr(i)
yield i

list(to_chr([115, 108, 101, 101, 112]))

> ['s', 'l', 'e', 'e', 'p']

當然上面的例子其實可以很簡單實現

1
2
1. [chr(x) for x in [115, 108, 101, 101, 112]]
2. map(lambda x: chr(x), [115, 108, 101, 101, 112])

原寫法

1
2
3
4
5
6
def to_chr(y):
t = []
for i in y:
t.append(chr(i))
return t
to_chr([115, 108, 101, 101, 112])