Jimmy 的架站筆記

嗨~我是 Jimmy!我可能不是你認識的第 1 個 Jimmy,但一定是最帥的那個。


Python Iterator 介紹

By Jimmy 2023-08-29
發表於 python
Python Iterator 介紹

Python Iterator 常常會和 Iterable object 一起搞混,這篇就來介紹一下 Python 中的 Iterator。

延伸閱讀:Python Iterable Objects 介紹

1. 定義

Python Iterator 的定義為:符合 Python 中的 Iterator Protocol,或是一個有 __iter__()__next__() methods 的 object。

vowels = ['a', 'e', 'i', 'o', 'u']
print(hasattr(vowels, '__iter__'))
True
print(hasattr(vowels, '__next__'))
False

# 可以用 iter() 來宣告 iterator object
vowels_iter = iter(vowels)
print(hasattr(vowels_iter, '__iter__'))
True
print(hasattr(vowels_iter, '__next__'))
True

可以用 collection module 來判斷是不是 iterator:

# Python 3.10+ 請用以下這行 import
from collections.abc import Iterable, Iterator
# Python 3.9- 請用以下這行 import
from collections import Iterable, Iterator

vowels = ['a', 'e', 'i', 'o', 'u']
print(isinstance(vowels, Iterable))
True
print(isinstance(vowels, Iterator))
False

vowels_iter = iter(vowels)
print(isinstance(vowels_iter, Iterable))
True
print(isinstance(vowels_iter, Iterator))
True

2. Iterator v.s. Iterable Object

那 iterator 和 iterable 又什麼差別呢?通常只要可以執行 iteration 的,就可以稱為 iterable object,最單純的方法,就是看可不可以用 for loop 去 iterate 每個 item。

那 Iterator 到底是用來做什麼用的呢?我們可以舉 list object 為例:

宣告了一個 list object 後,Python 會將這個 list object 存在記憶體當中,也因此宣告完 list object 後,你可以隨時取得這個 list object 的任意 item。

但這樣會有一個問題:當這個 list object 有很多 items 的時候,就會吃掉很多記憶體資源,因此 iterator 就是用來解決這類問題的。

list object 的 iterator 版本就稱為 list iterator object。list iterator object 和普通的 list object 最大的不同就在於執行方式,不像 list object 會將所有 items 載入記憶體,list iterator object 宣告後就只能 iterate 所有 items 一次,有點像是,我 iterate 完一個 item 後,就把控制權丟出去,並且只需要記得目前這個 iterator iterate 到哪個 item 就好,等到需要 iterate 的時候,再繼續 iterate 下一個 item,有點類似 linked list 的概念。

因為不需要將所有 items 都載入到記憶體,所以記憶體的用量通常會少滿多的,不過也因此無法存取到這個 list iterator object 的基本屬性,ex: len。

vowels = ['a', 'e', 'i', 'o', 'u']
print(vowels[2])
# 可以隨時取得 list object 的任意元素
'i'

vowels_iter = iter(vowels)
print(vowels_iter[2])
TypeError: 'list_iterator' object is not subscriptable

# 只能用 next 來 iterate iterator 的 items,且執行一次 next,就像是將 linked list 的指標往後挪一個 item
print(next(vowels_iter))
'a'
print(next(vowels_iter))
'e'
print(next(vowels_iter))
'i'
print(next(vowels_iter))
'o'
print(next(vowels_iter))
'u'
# iterate 到最後一個 item 後,再執行 iterator 的話,就會噴 StopIteration 的 exception
print(next(vowels_iter))
StopIteration

記憶體用量比較:

vowels = ['a', 'e', 'i', 'o', 'u']
print(getsizeof(vowels))
104 (Bytes)

vowels_iter = iter(vowels)
print(getsizeof(vowels_iter))
48 (Bytes)

所以,iterator 一定是 iterable object,但 iterable object 不一定是 iterator

3. 宣告 Iterator

3.1 iter function

iter(object)
iter(object, sentinel)
list_instance = [1, 2, 3, 4]
print(iter(list_instance))
<list_iterator object at 0x1024d6410>
class DoubleIt:
    def __init__(self):
        self.start = 1

    def __iter__(self):
        return self

    def __next__(self):
        self.start *= 2
        return self.start
    
    __call__ = __next__

my_iter = iter(DoubleIt(), 16)
print(my_iter)
<callable_iterator object at 0x104873ee0>

for x in my_iter:
    print(x)
2
4
8

3.2 generator

generator 也是一種 iterator,可以參考另一篇文章:Python Generator 介紹

參考資料

Python進階技巧 (6) — 迭代那件小事:深入了解 Iteration / Iterable / Iterator / __iter__ / __getitem__ / __next__ / yield
Python Iterators - W3Schools
Iterator Protocol — Python 3.11.4 documentation
[Python教學]Python Comprehension語法應用教學
Python iter(): iter() Parameters, What is ITER () in Python?


你可能也會喜歡

Python 教學 3 - File Handling -Read File, Write File

Python 教學 3 - File Handling -Read File, Write File

筆記一下在 Python 中讀寫檔案的方式 1. open Function - 針對檔案做操作 Python 提供了 open function 可以針對檔案進行一些操作: 1.1 filename 第一個參數是 filename,可以是相對路徑也可以是絕對路徑。 1.2 mode 用來決定開啟檔案的用途: 也可以決定要用什麼模式開啟檔案: 2. Read File - 讀取檔案

Read More