如何理解Python中的iterator對象

轉載請注明出處:http://www.itdecent.cn/u/5e6f798c903a
[^*] 表示注腳,在文末可以查看對應連接,但簡書不支持該語法。

迭代器是表示數(shù)據(jù)流的對象。

迭代器對象自身需要支持以下兩個方法,這兩個共同構成了迭代器協(xié)議:[^7]

  • iterator.__iter__()

    返回迭代器對象本身。由于實現(xiàn)了 __iter__ 對象都是屬于 IterableObjc ,因此迭代器也屬于 IterableObjc;并且在其它接受 IterableObjc 的地方,也多半可以接受迭代器。

  • iterator.__next__()

    返迭代器中的下一個項。重復調用迭代器的 __next__() 方法(或通過內置函數(shù)next() 重復調用迭代器),將返回流中連續(xù)的項。當沒有再無數(shù)據(jù)可供使用時,便會拋出 StopIteration 異常,這時表明該迭代器對象已經(jīng)耗盡,若此后仍試圖調用該迭代器的 __next__() 方法,將會再次拋出 StopIteration 異常。[^4]

    一旦迭代器的 __next__() 方法拋出 StopIteration,則必須在后續(xù)調用中繼續(xù)拋出異常。不遵從此特性的實現(xiàn)被視為不正確。[^7]

如果容器支持不同類型的迭代,則可以提供額外的方法來專門請求這些迭代類型的迭代器(支持多種迭代形式的對象的一個例子是樹結構,它支持 breadth-first 和 depth-first 兩種遍歷方式)。[^7]

Python 定義了多個迭代器對象,以支持對如下類型進行迭代:常規(guī)(general)序列類型和特殊(specific)序列類型、字典以及其它專業(yè)表單(specialized forms)。除迭代器協(xié)議的實現(xiàn)之外,其實特定類型并不重要。[^7]

1. 迭代器與 for 循環(huán)

將迭代器用于 for 循環(huán)時,for 循環(huán)仍會調用 iter() 來處理迭代器對象,然后通過 next() 逐一獲取每個元素,直至 __next__ 拋出 StopIteration 為止。注意:將某個迭代器對象傳遞給 iter() 后,只會返回指向該迭代器的引用,并不會創(chuàng)建具備新id的迭代器對象。

>>> aa = [1,2,3,]
>>> bb = iter(aa)
>>> bb
<list_iterator object at 0x000001B393436E48>
>>> cc = iter(bb)
>>> cc # bb和cc引用同一個對象
<list_iterator object at 0x000001B393436E48>

通常情況下,如果反復嘗試將某個迭代器用于 for 循環(huán),其實在第一次循環(huán)結束時就會耗盡該迭代器,之后只會反復使用這個已被耗盡的迭代器,看起來如同在使用一個空容器。[^4]

>>> aa = [1,2,3,]
>>> bb = iter(aa)
>>> for i in bb:
    print(i)

    
1
2
3
>>> for i in bb:
    print(i)

    
>>> 

但是,如果在__iter__ 中重置相關變量,則可讓迭代器反復用于for循環(huán),并且每次都有輸出。

class IteratorObjc:
    def __iter__(self):
        self._count = 0
        return self

    def __next__(self):
        while self._count < 3:
            self._count += 1
            return self._count

class IteratorObjc:
    """
    在這種情況下,每次調用__iter__方法時,
    會返回實例對象自身,不會創(chuàng)建具備新id的迭代器對象。
    """
    def __iter__(self):
        # 重置_count,便可反復進行迭代
        self._count = 0
        # 調用時返回實例自身
        return self

    def __next__(self):
        while self._count < 3:
            self._count += 1
            return self._count

a_iterator = IterableObjc()
for i in a_iterator:
    print(i, end=',')
print()
for i in a_iterator:
    print(i, end=',')

2. 迭代器與內置函數(shù)

由于迭代器也屬于 IterableObjc,所以迭代器也可直接用于如下內置函數(shù):

  • any(iterable)
  • class list([iterable])
  • map(function, iterable, ...)
  • ....

通常情況下,如果反復將某個迭代器傳遞給內置函數(shù)。在第一次使用該迭代器時就會耗盡該迭代器,之后只會反復使用這個已被耗盡的迭代器,看起來如同在使用一個空容器。

>>> aa = [1,2,3,]
>>> bb = iter(aa)
>>> list(bb)
[1, 2, 3]
>>> list(bb)
[]

但是,如果在__iter__ 中重置相關變量,則可讓迭代器反復用于內置函數(shù)。

class IteratorObjc:
    def __iter__(self):
        self._count = 0
        return self

    def __next__(self):
        while self._count < 3:
            self._count += 1
            return self._count


a_iterator = IterableObjc()
print(list(a_iterator))
print(list(a_iterator))

輸出

[1, 2, 3]
[1, 2, 3]

3. itertools

10.1. itertools — Functions creating iterators for efficient looping

itertools 模塊提供了眾多用于創(chuàng)建迭代器的函數(shù)。下面簡要介紹幾個:

  • count() 函數(shù)返回的迭代器可產生一串連續(xù)的整數(shù),并且通過該迭代器可產生無限個整數(shù)。與內置函數(shù) range() 不同,count() 不需要通過參數(shù)來設定上線。

    >>> from itertools import count
    >>> counter = count(start=10)
    >>> next(counter)
    10
    >>> next(counter)
    11
    
  • cycle() 函數(shù)會把所接受的可迭代對象轉換為一個無限循環(huán)的迭代器。

    >>> from itertools import cycle
    >>> colors = cycle(['red', 'white', 'blue'])
    >>> next(colors)
    'red'
    >>> next(colors)
    'white'
    >>> next(colors)
    'blue'
    >>> next(colors)
    'red'
    
  • islice() 函數(shù)會截取輸入迭代器的一部分,并把這部分作為輸出迭代器返回

    >>> from itertools import islice
    >>> colors = cycle(['red', 'white', 'blue'])  # infinite
    >>> limited = islice(colors, 0, 4)            # finite
    >>> for x in limited:                    # so safe to use for-loop on
    ...     print(x)
    red
    white
    blue
    red
    

注腳:
[1] 語言參考 - 3.1. Objects, values and types
[2] 標準庫 8.4. collections.abc — Abstract Base Classes for Containers
[3] Iterables vs. Iterators vs. Generators | 完全理解 Python 迭代對象、迭代器、生成器
[4] Glossary 術語表
[5] iter(object[, sentinel])
[6] 語言參考 - 8.3. The for statement
[7] 標準庫 - 4.5. terator Types
[8] 語言參考 - 3.3.7. Emulating container types
[9] 語言參考 -3.2. The standard type hierarchy

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容