1 Iterable
我們一般稱Iterable
為可迭代對象
。Python 中任意的對象,只要它定義了可以返回一個迭代器的__iter__
方法,或者定義了可以支持下標索引的__getitem__
方法,那么它就是一個可迭代對象。我們常用到的集合數據類型都是 Iterable。例如列表(list)、元組(tuple)、字典(dict)、集合(set)、字符串(str)等。
我定義了一個列表 numlist,打印出該列表的方法。
numlist = [1, 2, 3]
print(numlist)
print(numlist.__iter__) # 調用__iter__方法
print(numlist.__getitem__) # 調用__getitem__方法
運行結果如下:
根據運行結果,我們可知列表就是個可迭代對象。Python 的collections
庫有個isinstance()
函數。可以用來判斷一個對象是否是 Iterable 對象。
from collections import Iterable
isinstance({}, Iterable)
isinstance((), Iterable)
isinstance(999, Iterable)
運行結果為:
如果我們每次都要使用這個函數來判斷一個對象是否為可迭代對象,這樣操作有點麻煩。有沒有快速判定的方法呢?答案是肯定的。可以直接使用 for 循環進行遍歷的對象就是可迭代對象。
除此之外,generator(生成器)
和帶 yield 的 generator function
也是可迭代的對象。
2 Iterator
Iterator
是迭代器的意思。任意對象,只要定義了next()
(Python 2 版本)或者__next__()
(Python 3 版本) 方法,那么它就是一個迭代器。迭代器中還有另一個函數__iter__()
,它和 next() 方法形成迭代器協議。
iter()
返回主要是返回迭代器對象本身,即return self
。如果你自己定義個迭代器,實現該函數就能使用for ... in ...
語句遍歷了。next()
獲取容器中的下一個元素,當沒有可訪問元素后,就拋出StopIteration
異常。
遍歷迭代器有兩個方式。一種是使用 next() 函數;另一種則是使用 for each 循環,本質上就是通過不斷調用 next() 函數實現的。
from collections import Iterator
numlist = [1, 2, 3]
# 將數組轉化為迭代器
ite1 = iter(numlist)
print(ite1)
for i in ite1:
print(i)
print("=========")
ite2 = iter(numlist)
while True:
try:
num = ite2.__next__()
print(num)
except StopIteration:
break
值得注意的是一個 Iterator 只能遍歷一次。
3 generator
generator 翻譯成中文是生成器。生成器也是一種特殊迭代器。它其實是生成器函數返回生成器的迭代,“生成器的迭代器”這個術語通常被稱作”生成器”。yield 是生成器實現__next__()
方法的關鍵。它作為生成器執行的暫停恢復點,可以對 yield 表達式進行賦值,也可以將 yield 表達式的值返回。任何包含 yield 語句的函數被稱為生成器。
yield是一個語法糖,內部實現支持了迭代器協議,同時yield內部是一個狀態機,維護著掛起和繼續的狀態。
個人認為,生成器算是 Python 非常棒的特性。它的出現能幫助大大節省些內存空間。假如我們要生成從 1 到 10 這 10 個數字,采用列表的方式定義,會占用 10 個地址空間。采用生成器,只會占用一個地址空間。因為生成器并沒有把所有的值存在內存中,而是在運行時生成值。所以生成器只能訪問一次。
創建一個從包含 1 到 10 的生成器的例子。
gen = (i for i in range(10))
print(gen)
for i in gen:
print(i)
運行結果如下:
帶有 yield 關鍵字 的例子。重點關注運行結果,這能讓你對 yield 有更深的認識。
def testYield(n):
for i in range(n):
print("當前值: ", i)
yield doubeNumber(i)
print("第 ", i, " 次運行")
print("testYield 運行結束")
def doubeNumber(i):
return i*2
if __name__ == '__main__':
for i in testYield(3):
print(i, "===", i)
運行結果如下:
上篇閱讀:Python 繪圖,我只用 Matplotlib(二)
推薦閱讀:爬蟲系列的總結