python迭代器簡單理解 __iter__和__next__方法
阿新 • • 發佈:2021-12-11
在使用for語句的時候,相當於python內部把for後面的物件使用了iter()方法。
a = [1, 2, 3]
for i in a:
do_something()
for i in iter(a):
do_something()
iter()的返回是一個迭代物件,主要對映到了類裡的__iter__()方法。
對於使用iter()方法的物件,返回值為物件中的__iter__()方法的返回值。
iter()方法返回的是一個實現了__next__()方法的物件,由該物件實現的__next__()方法來完成實際的迭代。
class Node: def __iter__(self): return iter([1, 2, 3]) if __name__ == "main": n = Node() for i in n: print(i)
結果為:
1
2
3
Iterable:有迭代能力的物件,一個類,實現了__iter__(),就認為有迭代能力,通常此函式必須返回一個實現了__next__()的物件,如果自己實現了,可以返回self(返回值不是必須的)。
Iterator:迭代器,同時實現了__iter__()和__next__()的物件。(若某個自定義類只實現了__next__()而未實現__iter__()則會報錯)
在呼叫iter()方法的時候(例如for迴圈時),生成了一個迭代物件,要求__iter__()返回一個實現了__next__()的物件,可通過next()方法訪問這個物件的下一個元素。如果不新增StopIteration異常,會不斷迭代,for迴圈會捕捉這個異常並停止迭代。
class MyIter: def __init__(self): self._start = 0 def __iter__(self): return self def __next__(self): if self._start < 10: self._start += 1 return self._start else: raise StopIteration if __name__ == '__main__': a = MyIter() for i in a: print(i)
結果:
1
2
3
4
5
6
7
8
9
10
如果同時實現了__iter__()和__next__()方法,且__iter__()沒有返回self,呼叫iter方法時會返回__iter__()返回的結果
class MyIter:
def __init__(self):
self._start = 0
def __iter__(self):
return iter([1, 2, 3])
def __next__(self):
if self._start < 10:
self._start += 1
return self._start
else:
raise StopIteration
if __name__ == '__main__':
a = MyIter()
for i in a:
print(i)
結果:
1
2
3
呼叫iter()方法時,iter()僅會被呼叫一次,next()則會多呼叫多次。
具體體現:
class MyIter:
def __init__(self):
self._start = 0
def __iter__(self):
self._start += 8
return self
def __next__(self):
if self._start < 10:
self._start += 1
return self._start
else:
raise StopIteration
if __name__ == '__main__':
a = MyIter()
for i in a:
print(i)
結果:
9
10
迭代器的優點:
- 如果採用列表的方式遍歷,會將列表中所有內容載入記憶體;如果使用迭代器,只有呼叫了next()方法時才會返回對應的結果,可以節約記憶體。
- 不依賴索引的讀取方式。
迭代器的缺點: - 只能往後取值,不能往前取值;不能指定某一個值。
- 無法預測迭代器的長度。
不能指定某一個值體現於:
a = iter([1, 2, 3])
print(a[1])
Traceback (most recent call last):
File "D:/Project/python_fundamental/iterator_try/main.py", line 23, in <module>
print(a[1])
TypeError: 'list_iterator' object is not subscriptable