Python語法—迭代器、生成器

是皮皮攀呀,發表於2019-02-28

Python語法—迭代器、生成器

迭代器

迭代器物件要求支援迭代器協議的物件,在Python中,支援迭代器協議就是實現物件的__iter__()和next()方法。其中__iter__()方法返回迭代器物件本身;next()方法返回容器的下一個元素,在結尾時引發StopIteration異常。

__iter__()和next()方法

這兩個方法是迭代器最基本的方法,一個用來獲得迭代器物件,一個用來獲取容器中的下一個元素。
對於可迭代物件,可以使用內建函式iter()來獲取它的迭代器物件。
通過iter()方法獲得了list的迭代器物件,然後就可以通過next()方法來訪問list中的元素了。當容器中沒有可訪問的元素後,next()方法將會丟擲一個StopIteration異常終止迭代器。
其實,當我們使用for語句的時候,for語句就會自動的通過__iter__()方法來獲得迭代器物件,並且通過next()方法來獲取下一個元素。

迭代器和可迭代物件

對於一個可迭代物件,如果它本身又是一個迭代器物件,就會有下面的 問題,就沒有辦法支援多次迭代。
為了解決上面的問題,可以分別定義可迭代型別物件和迭代器型別物件;然後可迭代型別物件的__iter__()方法可以獲得一個迭代器型別的物件。

class Zrange:
    def __init__(self, n):
        self.n = n
 
    def __iter__(self):
        return ZrangeIterator(self.n)
 
class ZrangeIterator:
    def __init__(self, n):
        self.i = 0
        self.n = n
 
    def __iter__(self):
        return self
 
    def next(self):
        if self.i < self.n:
            i = self.i
            self.i += 1
            return i
        else:
            raise StopIteration()    
 
zrange = Zrange(3)
print zrange is iter(zrange)         
 
print [i for i in zrange]
print [i for i in zrange]

生成器

在Python中,使用生成器可以很方便的支援迭代器協議。生成器通過生成器函式產生,生成器函式可以通過常規的def語句來定義,但是不用return返回,而是用yield一次返回一個結果,在每個結果之間掛起和繼續它們的狀態,來自動實現迭代協議。

也就是說,yield是一個語法糖,內部實現支援了迭代器協議,同時yield內部是一個狀態機,維護著掛起和繼續的狀態。

生成器表示式

在開始介紹生成器表示式之前,先看看我們比較熟悉的列表解析( List comprehensions),列表解析一般都是下面的形式。

[expr for iter_var in iterable if cond_expr]

生成器表示式的語法和列表解析一樣,只不過生成器表示式是被()括起來的,而不是[]

(expr for iter_var in iterable if cond_expr)

遞迴生成器

生成器可以像函式一樣進行遞迴使用的,下面看一個簡單的例子,對一個序列進行全排列:

def permutations(li):
    if len(li) == 0:
        yield li
    else:
        for i in range(len(li)):
            li[0], li[i] = li[i], li[0]
            for item in permutations(li[1:]):
                yield [li[0]] + item
 
for item in permutations(range(3)):
    print item
    ```


#以上內容整理自summercamp中的學習資料。

相關文章