08-Python迭代器與生成器

迭代器

什麼是迭代器
  • 迭代是Python最強大的功能之一,是訪問序列中元素的一種方式。
  • 迭代器是一個可以記住遍歷的位置的對象。
  • 迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。迭代器只能往前不會後退。
  • 迭代器有兩個基本的方法:iter() 和 next()。
可迭代對象
  • 字符串、列表、元組對象等都是可迭代對象
  • 字符串、列表、元組對象等都可以創建迭代器

也就是說:

字符串、列表、元組對象等暫時不是迭代器,暫時不能被迭代。但是,它們成爲迭代器之後就可以被迭代了,如for循環。

利用可迭代對象Iterable創建迭代器Iterator
l=[1,2,3,4]     #l:可迭代對象
i=iter(l)       #i:迭代器
print(next(i))     #輸出1
print(next(i))     #輸出2
print(i.__next__())     #輸出3

解釋:

  • iter()函數可以將可迭代對象創建爲迭代器
  • 利用next函數可以得到下一個元素值
  • 迭代器能夠記住遍歷的位置,所以可以依次調用next()
  • 可迭代對象:Iterable
  • 迭代器:Iterator
  • 可迭代對象不能被迭代,不能調用next()。成爲迭代器之後纔可以。

注意:

遍歷完畢後,若再次調用next()函數,則會拋出異常:StopIteration,處理此異常即可。

處理StopIteration異常
try:
    l=[1,2]
    i=iter(l)
    print(next(i))     #輸出1
    print(next(i))     #輸出2
    print(next(i))     #拋出異常
except StopIteration as stopIteration:
    print("遍歷完成") 
刨析for循環

for循環實現了序列的遍歷,那它怎麼實現的呢?

for循環做的三件事:

  1. 創建迭代器
  2. 調用next方法
  3. 處理StopIteration異常

模擬for循環:

a=[100,200,300,400,500]
j=None
i=iter(a)   #1.創建迭代器
while(True):
    try:
        j=next(i)    #2.調用next方法
    except StopIteration as stopIteration:      #3.處理StopIteration異常
        break
    print(j)

結果:

100
200
300
400
500

生成器

什麼是生成器?
  • 生成器是一種特殊的迭代器。
  • 普通的迭代器將所有數據存放在內存中,極其佔用內存空間。
  • 生成器不將數據存入內存,而是通過計算得到數據
生成式生成器
a=(x*x for x in range(4))
print(next(a))     #輸出0
print("---------------------")
for i in a:         #輸出1、4、9
    print(i)

解釋:

  • 生成式生成器的語法與列表生成式相似,但用小括號( )包裹。列表生成式用[ ]包裹。
  • 數據不會存放在內存中,每一個調用next函數,就會計算一次數據。
  • 使用生成器的好處是:節約內存空間。
函數生成器
  • 函數生成器使用關鍵字yield來產生數據。
  • 通過next()來得到yield產生的數據
def get():
    yield 1     
    yield 2
g=get()
print(next(g))  #輸出1
print(next(g))  #輸出2

解釋:

  • 依次產生1和2,第三次調用next()則報錯
  • 運行yield語句後,python立即設置斷點,停止運行此函數,等待下一次調用next()
  • 每次運行,將從上一次的斷點處(即上一個yield後)開始運行。
函數生成器-send
  • 通過send函數得到下一個值
  • send函數還可以傳入一個值,這個值將被yield接收到
def func():
    count1 = yield 1
    print("count1=" , count1)
    count2 = yield 2
    print("count2=" , count2)
    yield 3
g = func()
print(g.send(None))
print(g.send(2))

結果:

1
count1= 2
2

解釋:

  • count1 = yield 1是賦值語句,先執行等號右邊。
  • 運行yield語句後,暫停運行此函數,所以第一次並沒有接收值。所以第一次通過send得到值需要用send(None)。
  • 此處的知識可以運用到協程上。

應用-斐波那契序列

可以得到無限多個斐波那契序列中的元素:

def fib():
    a=1
    b=1
    yield a
    yield b
    while(True):
        yield a+b
        temp=a+b
        a=b
        b=temp
f = fib()
for i in range(10):
    print(next(f),end=" ")

結果:

1 1 2 3 5 8 13 21 34 55 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章