Python中的迭代器


迭代器:iterator
可迭代對象:iterable

迭代器

在本文中,我們將學習迭代器是如何工作的,以及如何使用 __iter__()__next__() 方法構建自己的迭代器。

迭代器(Iterator)是可以迭代的對象,在 Python 中無處不在。它們在 for 循環、推導式、生成器等中得到了優雅的實現,但卻隱藏在顯而易見的地方。

Python 中的迭代器只是一個可以迭代的對象。一個每次僅僅返回一個元素的對象(有點像擠牙膏)。從技術上講,Python 迭代器對象必須實現兩個魔法方法:__iter__()__next__()方法,統稱為迭代器協議(iterator protocol)。

如果我們可以從一個對象中得到一個迭代器,那么這個對象就被稱為可迭代對象(iterable)。Python 中的大多數內置數據結構(容器)都是可迭代對象,比如 list列表、 tuple元組、 str字符串等等。iter ()函數(反過來調用__iter__()方法)從它們中返回一個迭代器。

遍歷迭代器

我們使用 next() 函數手動遍歷迭代器的所有元素。當我們到達結尾時,如果沒有更多的數據要返回,它將引發 StopIteration異常。

示例:

# 定義一個列表
my_list = [4, 7, 0, 3]

# 使用iter()返回一個迭代器對象
my_iter = iter(my_list)

# 使用next()方法依次遍歷
print(next(my_iter))  # 將打印 4
print(next(my_iter))  # 將打印 7

# next(obj) 和 obj.__next__()效果一樣
print(my_iter.__next__())  # 將打印 0
print(my_iter.__next__())  # 將打印 3

next(my_iter)  # 將會引起 StopIteration 異常

輸出結果:

4
7
0
3
Traceback (most recent call last):
  File "<string>", line 24, in <module>
    next(my_iter)
StopIteration

一種更優雅的自動迭代方式是使用 for 循環。這樣一來,我們可以遍歷任何可以返回迭代器的對象,例如列表、字符串、文件等等。

示例:

# 定義一個列表
my_list = [4, 7, 0, 3]

# 使用for循環遍歷
for i in my_list:
    print(i)

迭代器中的for循環

正如我們在上面的例子中看到的,for循環能夠自動遍歷列表。實際上,for 循環可以遍歷任何可迭代的對象。讓我們仔細看看 for 循環是如何在 Python 中實現的。

# 從可迭代對象中創建一個迭代器對象
iter_obj = iter(iterable)

# 開啟無限循環
while True:
    try:
        # 遍歷元素
        element = next(iter_obj)
        # 對元素進行一些操作
        pass
    except StopIteration:
        # 如果引起StopIteration則終止循環
        break

由此可見,for 循環在內部通過對可迭代對象(iterable)調用 iter()方法,來創建出一個迭代器(iterator)對象 iter_obj

笑不活的是,這個 for循環實際上竟是一個無限 while循環......意不意外,驚不驚喜😂。

自定義迭代器

在 Python 中,從零開始構建迭代器很容易,我們只需要實現 __iter__()__next__() 方法。

  • __iter__()方法返回迭代器對象本身. 如果需要,可以執行一些初始化。

  • __next__()方法必須返回序列中的下一項。在到達結尾時,以及在隨后的調用中,它必須引發StopIteration 異常。

下面,我們展示一個例子,它將給出每次迭代中2的下一次冪。其中冪指數從零開始到用戶設置的數字。

class PowTwo:
    """2的迭代器指數類"""

    def __init__(self, max=0):
        self.max = max

    def __iter__(self):
        self.n = 0
        return self

    def __next__(self):
        if self.n <= self.max:
            result = 2 ** self.n
            self.n += 1
            return result
        else:
            raise StopIteration


# 創建可迭代對象
numbers = PowTwo(3)

# 獲得一個迭代器
i = iter(numbers)

# 獲取下一個元素
print(next(i))
print(next(i))
print(next(i))
print(next(i))

執行后,輸出結果:

1
2
4
8

我們還可以使用 for 循環迭代迭代器類。

for i in PowTwo(5):
    print(i)

執行后輸出結果:

1
2
4
8
16
32

無限迭代器

迭代器對象中的項不必用盡。可以有無限迭代器(它永遠不會結束)。在處理這樣的迭代器時,我們必須小心。

下面是演示無限迭代器的一個簡單示例。

內置函數 iter()還有一種用法是:

iter(callable, sentinel) -> iterator

也就是說,它在調用時可以接收兩個參數 ,其中第一個參數必須是可調用對象(函數) ,第二個參數必須是哨兵。迭代器調用這個函數,直到返回的值等於哨兵。

我們知道python中的 int()函數默認總是返回0。因此,將它作為 iter(int,1)傳遞將返回一個調用 int()的迭代器,直到返回的值等於1。這種情況從來沒有發生,我們得到了一個無限迭代器。

不僅如此,我們還可以構建自己的無限迭代器。

class InfIter:
    """一個用來返回所有的奇數的無限迭代器類"""

    def __iter__(self):
        self.num = 1
        return self

    def __next__(self):
        num = self.num
        self.num += 2
        return num

執行后輸出結果:

1
3
5
...

其中...表示后續輸出無窮無盡。

因此,在遍歷這些類型的無限迭代器時,要注意包含終止條件。

其實,Python中還有一種更簡單的創建迭代器的方法,就是使用生成器 generator

---END


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM