Python迭代器
迭代器是可以迭代的對象。 在本教程中,您將瞭解迭代器的工作原理,以及如何使用__iter__
和__next__
方法構建自己的迭代器。
迭代器在Python中無處不在。 它們優雅地實現在循環,推導,生成器等中,但隱藏在明顯的視覺中。
Python中的迭代器只是一個可以迭代的對象。一個將一次返回數據的對象或一個元素。
從技術上講,Python迭代器對象必須實現兩個特殊的方法__iter__()
和__next__()
,統稱爲迭代器協議。
如果我們從中獲取一個迭代器,那麼一個對象被稱爲iterable
。 大多數Python中的內置容器是列表,元組,字符串等都是可迭代的。
iter()
函數(這又調用__iter__()
方法)返回一個迭代器。
通過Python中的迭代器迭代
使用next()
函數來手動遍歷迭代器的所有項目。當到達結束,沒有更多的數據要返回時,它將會引發StopIteration
。 以下是一個例子。
# define a list
my_list = [4, 7, 0, 3]
# get an iterator using iter()
my_iter = iter(my_list)
## iterate through it using next()
#prints 4
print(next(my_iter))
#prints 7
print(next(my_iter))
## next(obj) is same as obj.__next__()
#prints 0
print(my_iter.__next__())
#prints 3
print(my_iter.__next__())
## This will raise error, no items left
next(my_iter)
更優雅的自動迭代方式是使用for
循環。 使用for
循環可以迭代任何可以返回迭代器的對象,例如列表,字符串,文件等。
>>> for element in my_list:
... print(element)
...
4
7
0
3
循環如何實際工作?
在上面的例子中看到的,for
循環能夠自動通過列表迭代。
事實上,for
循環可以迭代任何可迭代對象。我們來仔細看一下在Python中是如何實現for
循環的。
for element in iterable:
# do something with element
實際上它是以類似下面的方式來實現的 -
# create an iterator object from that iterable
iter_obj = iter(iterable)
# infinite loop
while True:
try:
# get the next item
element = next(iter_obj)
# do something with element
except StopIteration:
# if StopIteration is raised, break from loop
break
所以在for
的內部,for
循環通過在可迭代的對象上調用iter()
來創建一個迭代器對象iter_obj
。
有意思的是,這個for
循環實際上是一個無限循環..。
在循環中,它調用next()
來獲取下一個元素,並使用該值執行for
循環的主體。 在所有對象耗盡後,引發StopIteration
異常,內部被捕獲從而結束循環。請注意,任何其他類型的異常都將正常通過。
在Python中構建自己的Iterator
構建迭代器在Python中很容易。只需要實現__iter__()
和__next__()
方法。
__iter__()
方法返回迭代器對象本身。如果需要,可以執行一些初始化。
__next__()
方法必須返回序列中的下一個項目(數據對象)。 在到達結束後,並在隨後的調用中它必須引發StopIteration
異常。
在這裏,我們展示一個例子,在每次迭代中給出下一個2
的幾次方。 次冪指數從零開始到用戶設定的數字。
class PowTwo:
"""Class to implement an iterator
of powers of two"""
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
現在可以創建一個迭代器,並通過它迭代如下 -
>>> a = PowTwo(4)
>>> i = iter(a)
>>> next(i)
1
>>> next(i)
2
>>> next(i)
4
>>> next(i)
8
>>> next(i)
16
>>> next(i)
Traceback (most recent call last):
...
StopIteration
也可以使用for
循環迭代那些迭代器類。
>>> for i in PowTwo(5):
... print(i)
...
1
2
4
8
16
32
Python無限迭代器
迭代器對象中的項目不必都是可耗盡的,可以是無限迭代器(永遠不會結束)。 處理這樣的迭代器時一定要小心。
下面是用來演示無限迭代器的一個簡單的例子。
內置的函數iter()
可以用兩個參數來調用,其中第一個參數必須是可調用對象(函數),而第二個參數是標頭。迭代器調用此函數,直到返回的值等於指定值。
>>> int()
0
>>> inf = iter(int,1)
>>> next(inf)
0
>>> next(inf)
0
可以看到,int()函
數總是返回0
,所以將它作爲iter(int,1)
傳遞將返回一個調用int()
的迭代器,直到返回值等於1
。這從來沒有發生,所以這樣就得到一個無限迭代器。
我們也可以建立自己的無限迭代器。 以下迭代器理論上將返回所有奇數。
class InfIter:
"""Infinite iterator to return all
odd numbers"""
def __iter__(self):
self.num = 1
return self
def __next__(self):
num = self.num
self.num += 2
return num
示例運行如下 -
>>> a = iter(InfIter())
>>> next(a)
1
>>> next(a)
3
>>> next(a)
5
>>> next(a)
7
當迭代這些類型的無限迭代器時,請注意指定終止條件。
使用迭代器的優點是它們可以節省資源。 如上所示,我們可以獲得所有奇數,而不將整個系統存儲在內存中。理論上,可以在有限的內存中計算有無限的項目。