一·迭代器
可以直接作用於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)