探討 Python 的生成器(Generator) - tsungjung411/python-study GitHub Wiki
- 若使用 for 迴圈,一般只能使用 range(...), enumerate(...)。
若使用 range(100000),則會產生 100000 個整數的清單,太佔記憶體空間了
- 若改用 while 迴圈控制,自己控制 i=i+1,就可以不需要 generator 了吧?
看起來是,所以感覺 generator 是多餘的?
- 但是如果把 while 的迴圈控制,打包成一個小函數,讓程式碼的可讀性高一點(Model 複雜產生元素, View 負責顯示),這時候 generator 就派上用場
程式碼:
even_list = [even for even in range(2,20,2)]
print('from the even list: ')
for even in even_list:
print(even)
# end-of-for
# 把上述的 [...] 直接換成 (...),就是一個 generator
even_generator = (even for even in range(2,20,2))
print('from the even generator: ')
for even in even_generator:
print(even)
# end-of-for
執行結果:
from the even list:
2
4
6
8
10
12
14
16
18
from the even generator:
2
4
6
8
10
12
14
16
18
程式碼:
def from_to(start, end):
idx = start
while idx < end:
yield idx # 執行後,後續的執行會暫停,並回傳 idx
idx = idx + 1
# end-of-while
# end-of-def
# 呼叫 from_to 生成器
for idx in from_to(10, 20):
print(idx)
# end-of-for
執行結果:
10
11
12
13
14
15
16
17
18
19
可以不用一次產生所有的整數,因此可以省去記憶體的空間
- 先用 print 輸出,測試沒問題,再把 print 換成 yield
程式碼:
def from_to(start, end):
idx = start
while idx < end:
print(idx) # 測試沒問題了,把 print 換成 yield, generator 就大功告成
idx = idx +1
# end-of-while
# end-of-def
# 呼叫 from_to 函數
from_to(10, 20)
執行結果:
10
11
12
13
14
15
16
17
18
19
- Model 複雜產生元素, View 負責顯示
程式碼:
# Model part
def fib(max):
'''
費波那西數列(Fibonacci Sequence)
idx: 0, 1, 2, 3, 4, 5, 6
fib: 0, 1, 1, 2, 3, 5, 8
'''
n, a, b = 0, 0, 1
while a <= max:
# print('[{}] {}'.format(n, a))
yield a
a, b = b, a + b
n = n + 1
# end-of-while
# end-of-def
# View part
for n in fib(100):
print(n)
# end-of-def
執行結果:
0
1
1
2
3
5
8
13
21
34
55
89
- 可以逐步生成下一個迭代的參數