您好,登錄后才能下訂單哦!
在學習python數據結構的過程中,可迭代對象,迭代器,生成器這些概念參雜在一起,難免讓初學者一頭霧水,今天就來捋捋這些概覽。
什么是可迭代對象,通俗的講就是可以直接通過for循環遍歷的對象就可稱為可迭代對象Iterable,可以使用isinstance()判斷一個對象是否是Iterable對象:
>>>from collections import Iterable
>>>isinstance([], Iterable)
True
>>>isinstance({}, Iterable)
True
>>>isinstance('123', Iterable)
True
>>>isinstance(123, Iterable)
False
可迭代對象并不指某種具體的數據類型,list, dict, set, str都是迭代對象,再比如打開狀態的files,sockets也是可迭代對象,可迭代對象是指代對象的一種屬性,代表該對象是可迭代的。可迭代對象實現了__iter__方法,該方法返回一個迭代器對象。
任何實現了__iter__和__next__方法的對象都是迭代器(python2是實現__iter__和next方法),__iter__返回迭代器自身,__next__返回容器中的下一個值,如果容器中沒有更多元素了,則拋出StopIteration異常。可以使用isinstance()判斷一個對象是否是Iterator對象:
>>>from collections import Iterator
>>>isinstance([], Iterator)
False
>>>isinstance({}, Iterator)
False
>>>isinstance('123', Iterator)
False
>>>isinstance((x for x in range(10)), Iterator)
True
其中(x for x in range(10))是生成器表達式,它返回的是一個生成器對象,不同于列表生成式[x for x in range(10)]返回一個list對象。生成器對象都是迭代器對象,但list, dict, str雖然是可迭代對象,但不是迭代器對象,可以使用iter()將list, dict, str等可迭代對象變成迭代器對象。
>>>isinstance(iter([]), Iterator)
True
>>>isinstance(iter('123'), Iterator)
True
python的迭代器對象表示一個數據流,可以將這個數據流看作一個有序序列,但我們并不知道序列的長度,只能不斷通過調用next()函數實現按需計算下一個數據,因此迭代器的計算是惰性的,只有在需要返回下一個數據時它才計算,迭代器的這種特性可以大大減少內存的開銷,迭代器對象甚至可以表示一個無限大的數據流,而讓list, dict或者str存儲一個無限大的數據流是不可能的。
下面我們通過迭代器來實現斐波那契數列:
from collections import Iterable
from collections import Iterator
class Fib:
def __init__(self, max):
self.n, self.max = 0, max
self.a, self.b = 0, 1
def __iter__(self):
return self
def __next__(self):
if self.n < self.max:
self.n += 1
self.a, self.b = self.b, self.a + self.b
return self.a
else:
raise StopIteration
if __name__ == '__main__':
fib = Fib(10)
print(isinstance(fib, Iterable)) # True
print(isinstance(fib, Iterator)) # True
print([e for e in fib]) # [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
Fib既是一個可迭代對象(因為它實現了__iter__方法),又是一個迭代器(因為實現了__next__方法)。實例變量a和b用于維護迭代器內部的狀態。每次調用next()方法的時候做兩件事:
為下一次調用next()方法修改狀態,為當前這次調用生成返回結果。
迭代器就像一個懶加載的工廠,等到有人需要的時候才給它生成值返回,沒調用的時候就處于休眠狀態等待下一次調用。
生成器是一種特殊的迭代器,不過這種迭代器更加優雅。它不需要再像上面的類一樣寫__iter__()和__next__()方法了,只需要一個yiled關鍵字。
用生成器來實現斐波那契數列的例子是:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
n = n + 1
a, b = b, b + a
yield a
f = fib(10)
print(f) # <generator object fib at 0x10d8cf888>
print([e for e in f]) # [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
fib函數中的yield關鍵字,將該函數變成了一個生成器,當執行f=fib(10)返回的是一個生成器對象,此時函數中的代碼并不會執行,只有顯示或隱示地調用next的時候才會真正執行里面的代碼,在每次調用next()方法時,遇到yield語句返回值并中斷,再次執行時從上次返回的yield語句處繼續執行。
生成器是python非常強大的特性,相比其他容器對象它更加節省內存,同時使用更少的代碼,使你的代碼更加的優雅,凡事以下結構都可以通過生成器重構:
def fun():
result = []
for ... in ...:
result.append(x)
return result
def fun_gen():
for ... in ...:
yield x
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。