python如何使用生成器函數實現可迭代對象

實際案例

實現一個可迭代對象的類,它能迭代出給定範圍內所有素數:

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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章