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