面向對象--05迭代器與生成器

一·迭代器

可以直接作用於for循環的對象統稱爲可迭代對象(Iterable)。

可以被next()函數調用並不斷返回下一個值的對象稱爲迭代器(Iterator)。

所有的Iterable均可以通過內置函數iter()來轉變爲Iterator。

對迭代器來講,有一個__next__()就夠了。在你使用for 和 in 語句時,程序就會自動調用即將被處理的對象的迭代器對象,然後使用它的__next__()方法,直到監測到一個StopIteration異常。

相關BIF: iter()    next()

一下爲IDLE環境下的演示

>>> string = 'tecent'
>>> it = iter(string)
>>> next(it)
't'
>>> next(it)
'e'
>>> next(it)
'c'
>>> next(it)
'e'
>>> next(it)
'n'
>>> next(it)
't'
>>> next(it)
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    next(it)
StopIteration
>>>

下面是for迭代的工作原理

string = 'tencent'
it = iter(string)
while True:
    try:
        each = next(it)
        print(each)
    except StopIteration:
        break

輸出結果

t
e
n
c
e
n
t
>>>


對應魔法方法:__iter__()     __next__()

我們以斐波那契數列進行演示

class Fibs:
    def __init__(self):
        self.a = 0
        self.b = 1
    def __iter__(self):
        return self
    def __next__(self):
        self.a,self.b = self.b,self.a+self.b
        return self.a

fibs = Fibs()
for each in fibs:
    if each<100:
        print(each)

以下是輸出結果

1
1
2
3
5
8
13
21
34
55
89


二·.生成器
生成器是這樣一個函數,它記住上一次返回時在函數體中的位置。對生成器函數的第二次(或第 n 次)調用跳轉至該函數中間,而上次調用的所有局部變量都保持不變。
生成器不僅“記住”了它數據狀態;生成器還“記住”了它在流控制構造(在命令式編程中,這種構造不只是數據值)中的位置。
生成器的特點:
     生成器是一個函數,而且函數的參數都會保留。
     迭代到下一次的調用時,所使用的參數都是第一次所保留下的,即是說,在整個所有函數調用的參數都是第一次所調用時保留的,而不是新創建的

yield 生成器的運行機制:
當你問生成器要一個數時,生成器會執行,直至出現 yield 語句,生成器把yield 的參數給你,之後生成器就不會往下繼續運行。 當你問他要下一個數時,他會從上次的狀態。開始運行,直至出現yield語句,把參數給你,之後停下。如此反覆
直至退出函數。(以上關於yield的描述,在後面列舉一個簡單的例子來解釋這段話)
yield的使用:

在python中,當你定義一個函數,使用了yield關鍵字時,這個函數就是一個生成器,它的執行會和其他普通的函數有很多不同,函數返回的是一個對象,而不是你平常所用return語句那樣,能得到結果值。如果想取得值,那得調用next()函數,如:

>>> c = h() #h()包含了yield關鍵字  
>>> #返回值  
>>> c.next()

每當調用一次迭代器的next函數,生成器函數運行到yield之處,返回yield後面的值且在這個地方暫停,所有的狀態都會被保持住,直到下次next函數被調用,或者碰到異常循環退出。

下面,來看看以下的例子代碼吧,是用來說明yield運行機制的。

def fib(max):  
    a, b = 1, 1  
    while a < max:  
        yield a 
        a, b = b, a+b  

#程序運行:
for n in fib(15):  
    print(n)


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