python如何使用生成器函式實現可迭代物件
阿新 • • 發佈:2019-01-28
實際案例
實現一個可迭代物件的類,它能迭代出給定範圍內所有素數:
pn = PrimeNumbers(1, 30)
for k in pn:
print k
- 1
- 2
- 3
輸出結果為:
2 3 5 7 11 13 17 19 23 29
- 1
解決方案:將該類的__iter__方法實現成生成器函式,每次yield返回一個素數。
有了解決方案後,我們首先要了解一下什麼是生成器函式。讓我們先看看如下程式碼:
def f():
print 'in f(), 1'
yield 1
print 'in f(), 2'
yield 2
print 'in f(), 3'
yield 3
g = f()
print type(g)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
其輸出結果為:
<type 'generator'>
- 1
誒,我們呼叫了f()卻沒有列印輸出我們設想的結果,這是為什麼呢?我們現在來看看這個輸出結果,它表示呼叫f()後的返回結果型別為generator型別,即返回的結果為生成器物件。那麼,我們將任何包含yield 語句的函式稱為生成器(函式)。當然,生成器不僅僅是包含yield語句的函式,更多關於生成器的知識請參閱廖雪峰的Python教程。
yield語句不會像return那樣返回值,而是每次產生多個值。每次產生一個值(使用yield語句),函式就會被凍結:即函式停在那點等待被重新喚醒。函式被重新喚醒後就從停止的那點開始執行。
將yield語句的知識補充完後,我們再回到生成器這個知識點。上面我們講到我們呼叫f()後返回一個生成器物件,其和迭代器物件類似,它也可以實現next()。(注:Python 3.X版本中為__next__()。)
那我們就在程式碼中實現next():
# g.next()
for x in g:
print x
- 1
- 2
- 3
其結果為:
in f(), 1
1
in f(), 2
2
in f(), 3
3
- 1
- 2
- 3
- 4
- 5
- 6
通過上述程式碼,我們又可發現g(生成器物件)也是一個迭代器物件。因此,我們就可以利用這一點解決我們的實際案例,程式碼如下:
# -*- coding: utf-8 -*-
class PrimeNumbers:
def __init__(self, start, end):
self.start = start
self.end = end
def isPrimeNum(self, k):
if k < 2:
return False
for i in xrange(2, k):
if k % i == 0:
return False
return True
def __iter__(self):
for k in xrange(self.start, self.end + 1):
if self.isPrimeNum(k):
yield k
if __name__ == "__main__":
for x in PrimeNumbers(1, 30):
print x
- 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
輸出結果為:
2
3
5
7
11
13
17
19
23
29