Python generator object 其實是 iterator 的一種,所以一樣有 iterator 的特性:
- 只能 iterate 一次
- 可以用 next function 取得 iteration 的下一個 item
延伸閱讀:Python Iterator 介紹
Table of Contents
1. 宣告 Python Generator
1.1 Generator Expression
Generator Expression 和 Comprehension 語法類似,只是將 expression 用 () 給包起來。
延伸閱讀:Python Comprehension 語法 – List Comprehension, Set Comprehension, Dict Comprehension
# List Comprehension 表示法
my_comprehension = [i for i in range(5)]
my_generator = (i for i in range(5))
print(my_comprehension)
[0, 1, 2, 3, 4]
print(my_generator)
<generator object <genexpr> at 0x104231970>
可以看到,用 generator expression 可以用來宣告 generator object。
如上述提到的,generator 其實算是 iterator 的一種,所以我們可以根據 iterator 的定義:有 __iter__()
和 __next__()
methods 的 object,來確認他是不是 iterator。
from collections.abc import Iterator
my_generator = (i for i in range(5))
print(hasattr(my_generator, '__iter__'))
True
print(hasattr(my_generator, '__next__'))
True
print(isinstance(my_generator, Iterator))
True
因此,generator 也依樣具備了 iterator 的特性:
my_generator = (i for i in range(5))
print(next(my_generator))
0
print(next(my_generator))
1
print(next(my_generator))
2
print(next(my_generator))
3
print(next(my_generator))
4
print(next(my_generator))
StopIteration
1.2 generator function
第二種宣告 generator 的方式,是使用 generator function,只要在 function 的定義中有出現 yield,那這個 function 就會變成 generator function
def yield_generator():
yield('Hello')
my_generator = yield_generator()
print(my_generator)
<generator object yield_generator at 0x1002749e0>
當執行 generator function 的時候,並不會真的執行 function,而是會 new 出一個 generator object,可以用 for loop 或是 next function 來 iterate 這個 generator object。
每當執行 next function 時,才會真的執行 generator function,碰到 yield 的時候會再把控制權丟出來,直到再次執行 next function,才會從上次 yield 的地方繼續往下執行,直到碰到下一個 yield:
def yield_generator():
print('start')
yield('Hello')
print('keep executing')
yield('world')
my_generator = yield_generator()
print(next(my_generator))
start
Hello
print(next(my_generator))
keep executing
world
print(next(my_generator))
StopIteration
可以用 while loop 和 yield 搭配使用:
def yield_generator(max):
n = 0
a = 2
while n < max:
yield(a)
a = a ** 2
n = n + 1
my_generator = yield_generator(3)
print(next(my_generator))
2
print(next(my_generator))
4
print(next(my_generator))
16
print(next(my_generator))
StopIteration
參考資料
產生器 generator – Python 教學 – STEAM 教育學習網
How to Use Generators and yield in Python
如果覺得我的文章有幫助的話,歡迎幫我的粉專按讚哦~謝謝你!