1. 程式人生 > >叠代器(Iterable)和for..in..的三種協議

叠代器(Iterable)和for..in..的三種協議

all 規則 sleep mos next cnblogs 數列 elf recent

一。叠代器協議

1. 叠代器協議:對象需要提供next方法,它要麽返回叠代中的下一項,要麽就引起一個StopIteration異常,以終止叠代

2. 可跌達對象:實現了叠代器協議的對象

3. 協議是一種約定,可叠代對象實現叠代器協議,在Python中,叠代是通過for ... in來完成的

二。簡單叠代器

以斐波那契數列為例,寫一個簡單的叠代器

>>> from collections import Iterable
>>> class Fib:
...     def __init__(self):
...         self.a,self.b 
= 0,1 ... def __iter__(self): ... return self ... def next(self): ... self.a,self.b = self.b,self.a + self.b ... if self.a > 100: ... raise StopIteration() ... return self.a ... >>> a = Fib() >>> for n in a: ... print n ...
1 1 2 3 5 8 13 21 34 55 89 >>> isinstance(a,Iterable) True >>>

Fib既是一個可叠代對象(因為它實現了__iter__方法),又是一個叠代器(因為實現了__next__方法)

再簡化一下,不用for....in....

>>> a = Fib()
>>> it = iter(a)
>>> next(it)
1
>>> next(it)
1
>>> next(it)
2
>>> next(it)
3 >>>

一個叠代器只叠代一次,重復跌代要獲得新的叠代器。

三。for...in... 協議

1. 協議A: __iter__ + next

這是叠代器的協議,和上面說的一樣,for..in.. 先調用iter(a) 讓a的__iter__返回一個叠代器,然後循環這個叠代器的next方法直到沒有下一個元素異常退出。

for...in... 首先執行跌達器,比如存在跌達和__getitem__就會以跌達器遍歷.

2. 協議B: __getitem__

>>> class B:
...     def __getitem__(self,n):
...         print n
...         time.sleep(2)
...         return a
... 
>>> b = B()
>>> for x in b:
...     print x
... 
0
a
1
a
2
a
3
a
4

n 一直循環的增長,直到有異常此循環才退出,一般作為下標索引遍歷

>>> class B:
...     def __init__(self):
...         self.l = [a,b,c,d,e]
...     def __getitem__(self,n):
...         return self.l[n]
... 
>>> b = B()
>>> for x in b:
...     print x
... 
a
b
c
d
e
>>> 

3. 協議C: yield關鍵字

>>> def c():
...     yield a
...     yield b
...     yield c
...     yield d
... 
>>> c1 = c()
>>> print next(c1),next(c1),next(c1),next(c1),next(c1)
a b c d
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> 

這是生成器(generator),是可叠代對象,不是一次性列出結果,用到了才按照某種規則得出結果,占用內存很少,用for...in...時不斷循環調用 next() 方法,每次 next() 後 yield 返回一個值並掛起,到下次 next() 從上次掛起的 yield 接著執行,yield 和 return 一樣返回值,生成器只叠代一次,因為沒有__iter__返回新的叠代對象。

叠代器(Iterable)和for..in..的三種協議