在 Python 中把鉴,迭代特性遠(yuǎn)比我們想象中運(yùn)用的多,很多我們平常忽略的東西都用到對象能迭代的特性径簿,比如
- for
- collection type construction and extension
- looping over text file line by line
- list, dict, set comprehension
- unpacking
- many built-in function
Iterable 與 Iterator
Iterable 返回一個 Iterator (通過定義 __iter__
方法)
Iterator 要求定義 __iter__
和 __next__
其中前者往往返回 self,后者逐個返回元素直到?jīng)]有元素時拋出 StopIteration
檢測一個對象是不是 Iterator 最好的方法是 isinstance(obj, abc.Iterator)
, 即是你的 obj 不是繼承自 abc.Iterator
,但只要你的對象實(shí)現(xiàn)了 __iter__
和 __next__
方法就會返回 True
還有要注意的一點(diǎn)是最好把 Iterable 和 Iterator 分開渺尘,原因是 Iterable 往往要求能多次迭代,而 Iterator 迭代完后就沒有了
一個最為普通的 Iterator
import re
RE_WORD = re.compile('\w+')
class Sentence:
def __init__(self, text):
self.words = RE_WORD.findall(text)
def __iter__(self):
return SentenceIterator(self.words)
class SentenceIterator:
def __init__(self, words):
self.words = words
self.index = index
def __next__():
try:
word = self.words[self.index]
except IndexError:
raise StopIteration
self.index += 1
return word
def __iter__():
return self
顯然這樣定義很繁瑣说敏,所以 Python 中有很多語法糖來幫助你 :)
Generator Function
Generator Function 是含有 yield 的函數(shù)鸥跟,調(diào)用 Generator Gunction 返回一個 Generator 對象,而 Generator 對象內(nèi)部實(shí)現(xiàn)了 Iterator 協(xié)議盔沫,因此支持迭代
class Sentence:
def __init__(self, text):
self.words = RE_WORD.findall(text)
def __iter__(self):
for word in self.words:
yield word
還可以讓我們上面 Sentence 的實(shí)現(xiàn)更加 Lazy医咨,節(jié)約內(nèi)存
class Sentence:
def __init__(self, text):
self.text = text
def __iter__(self):
for match in RE_WORD.finditer(self.text):
yield match.group()
Python 中類似 list comprehension, 還有 generator comprehension, 作為 generator function 的語法糖,generator comprehension 直接返回一個 generator 對象
class Sentence:
def __init__(self, text):
self.text = text
def __iter__(self):
return (match.group() for match in RE_WORD.finditer(self.text))
推薦閱讀: Generator Tricks for Systems Programmers