如何使用生成器函数实现可迭代对象?

需求:
实现一个可迭代对象的类,它能迭代给定范围的所有素数:
pn = PrimeNumber(1,30)
for k in pn:
print k,
输出结果:
2 3 5 7 11 17 19 23 29

实现过程:
思路:
将该类的__iter__方法实现成生成器函数,每次yield返回一个素数
代码:

class PrimeNumbers:
    def __init__(self,start,end):
        self.start = start
        self.end = end

    def isPrimeNum(self,k):
        if k < 2:    #素数指大于2的质数,这里排除小于2的数
            return False

        for i in range(2,k):   #如果能被k和1以外的数整除,返回False,非素数
            if k % i == 0:
                return False

        return True    # 前面都通过了,返回True,这里的k为素数

    def __iter__(self):  # 构建生成器:(集可迭代对象和迭代器的特性于一身,包括了__iter__和__next__方法,yiled是__next__方法的另一种表现形式)
        for k in range(self.start,self.end + 1):
            if self.isPrimeNum(k):
                yield k

if __name__=='__main__':
    list_number = []
    for x in PrimeNumbers(1,100):
        list_number.append(x)
    print(list_number)

=====================================================================================================================

from collections import Iterable

class PrimeNumbers(Iterable):
    def __init__(self,a,b):
        self.a = a
        self.b = b

    def __iter__(self):
        for k in range(self.a,self.b+1):
            if self.is_prime(k):
                yield k

    def is_prime(self,k):
        return False if k < 2 else all(map(lambda x:k % x,range(2,k)))

pn = PrimeNumbers(1,30)
for n in pn:
    print(n)

====================================================================================
>>> def f():  
...     print('in f 1')
...     yield 1
...     print('in f 2')
...     yield 2
...     print('in f 3')
...     yield 3
... 

>>> f()  # 包含yield的即为生成器对象,生成器对象同时有__iter__和__next__方法,使用生成器对象的好处是可以自动维护迭代状态。
<generator object f at 0x7f794c42ea40>

>>> g = f()

>>> from collections import Iterable,Iterator

>>> isinstance(g,Iterator)
True

>>> isinstance(g,Iterable)
True

>>> iter(g) is g
True

>>> next(g)
in f 1
1

>>> next(g)
in f 2
2

>>> next(g)
in f 3
3

>>> next(g)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-169-e734f8aca5ac> in <module>
----> 1 next(g)

StopIteration: 

>>> g = f()

>>> for x in g:
...     print(x)
... 
in f 1
1
in f 2
2
in f 3
3

>>> class XXX_Iterable(Iterable):
...     def __iter__(self):
...         yield 1
...         yield 2
...         yield 3
... 

>>> x = XXX_Iterable()

>>> 5 % 2
1

>>> if 5 % 2:
...     print(aaa)
... 
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-175-d8374d02d066> in <module>
      1 if 5 % 2:
----> 2     print(aaa)
      3 

NameError: name 'aaa' is not defined

>>> if 5 % 2:
...     print('aaa')
... 
... 
aaa

>>> 5 % 2 is True
False

>>> 4 % 2
0

>>> if 4 %2:
...     print('bbb')
... 

>>> for x in range(2,10):
...     print(x)
... 
2
3
4
5
6
7
8
9

>>> def is_prime(k):
...     if k < 2:
...         return False
...     for x in range(2,k):
...         if k % x == 0:
...             return False
...         return True
... 

>>> is_prime(2)

>>> range(2,2)
range(2, 2)

>>> for x in range(2,2)
  File "<ipython-input-184-19ce5b84b352>", line 1
    for x in range(2,2)
                       ^
SyntaxError: invalid syntax


>>> for x in range(2,2):
...     print(x)
... 

>>> for x in range(2):
...     print(x)
... 
0
1

>>> is_prime(4)
False

原文地址:https://www.cnblogs.com/Richardo-M-Q/p/13264178.html