網路上好多教程都說實作了 __iter__() 和 __next__() 方法的物件就是迭代器, 但是這種說法過于模糊了, 總會讓初學者創建出有問題的迭代器.
# 查看串列和串列迭代器,發現它們其實型別并不一樣
type([]) # list
type(iter([])) # list_iterator
# 可以認為 串列物件的 __iter__() 方法 回傳了一個 list_iterator 物件.
# 而 list_iterator 并不是串列的子類
type(iter([])).mro()
# [list_iterator, object]
# 看上面的代碼, list_iterator 就是一個普通的類
# 定義方式類似于 class list_iterator:
為什么串列的 __iter__() 沒有回傳 self , 而是回傳了一個新的物件?
回傳新物件的好處是 : 能夠確保一個迭代器實體只能被迭代一遍, 而且迭代器不會影響創建迭代器的物件的內容 (即不能影響 iter(obj) 里的 obj ).
比如一個串列迭代器只能被迭代一次, 而一個串列能被迭代無數次
l = [1]
l_iter = iter(l)
for i in l_iter:
print(i)
# 1
for i in l_iter:
print(i)
# 空的, l_iter 只能被迭代一次.
# 注意:創建迭代器的串列物件 l 沒有被改變
創建類似的迭代器
所以我們想要實作類似的迭代器,就要按如下語法創建
class N:
def __init__(self,n):
self.n = n
def __iter__(self):
# 我們不回傳原本的物件, 而是根據需要迭代的資料,創建一個新的迭代器物件
class N_iterator:
def __init__(self, n):
self.n = n
self.i = 0
def __iter__(self):
return self
def __next__(self):
i = self.i
if i < self.n:
self.i += 1
return i
else:
raise StopIteration('迭代結束!')
return N_iterator(self.n)
這樣做的好處是我們自定義的可迭代物件和Python內置的可迭代物件的行為變得一致了.
n = N(10)
n_iter = iter(n)
for i in n:
print(i)
# n 可以多次迭代
for i in n_iter:
print(i)
# n_iter 只能被迭代一次
本文首發于python黑洞網,博客園同步跟新
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/273118.html
標籤:Python
