1. 程式人生 > >迭代器、可迭代物件、生成器

迭代器、可迭代物件、生成器

 

迭代器與可迭代物件

1、定義:

可迭代物件:大部分容器如 list,truples,str,sets是可迭代物件,但是他們不是迭代器。可迭代物件實現了__iter__方法,返回一個迭代器,或者使用iter(“可迭代物件”)返回一個迭代器。

 

迭代器:迭代器提供了一種不依賴索引取值的方式,這樣可以遍歷沒有索引的可迭代物件,比如字典、集合、檔案等等,載入這一個元素至記憶體中隨後釋放,相比之下更節省記憶體,但是我們沒有辦法獲取迭代器的長度,而且只能往後依次取值。遍歷的方法使用next(“迭代器”)

 

2、程式碼示例

d={'a':1,'b':2,'c':3}
s = d.__iter__()  #s是一個迭代器

 

p = iter(“可迭代物件”)  #p是一個迭代器

 

#遍歷迭代器

next(p)

next(p)

 

3、for迴圈

在for迴圈中,Python將自動呼叫工廠函式iter()獲得迭代器,自動呼叫next()獲取元素,還完成了檢查StopIteration異常的工作。如下

a = (1, 2, 3, 4)

for key in a:

    print key

首先python對關鍵字in後的物件呼叫iter函式迭代器,然後呼叫迭代器的next方法獲得元素,直到丟擲StopIteration異常。

 

4、自定義一個迭代器:

class Fibs:

    def __init__(self):   #初始化

        self.a = 0

        self.b = 1

       

    def __next__(self):    #獲取下一個條目

        self.a, self.b = self.b, self.a + self.b

        return self.a

   

    def __iter__(self):    #返回迭代器

        return self

 

fibs = Fibs()    #產生一個物件

for f in fibs:    #迭代

    if f > 5:

        break

print(f)

>>>8

 

next(fibs)

>>>13

next(fibs)

>>>21

生成器
1)建立生成器

在一個一般函式中使用yield關鍵字,可以實現一個最簡單的生成器,此時這個函式變成一個生成器函式。

 

yield與return返回相同的值,區別在於return返回後,函式狀態終止,而yield會儲存當前函式的執行狀態,在返回後,函式又回到之前儲存的狀態繼續執行。

2)為何使用生成器

記憶體使用更加高效。比如列表是在建立的時候就分配所有的記憶體空間,而生成器僅僅是需要的時候才會產生。如果我們要讀取並使用的內容遠遠超過記憶體,但是需要對所有的流中的內容進行處理,那麼生成器是一個很好的選擇。

3)生成器函式的特點

ü  生成器函式包含一個或者多個yield

ü  當呼叫生成器函式時,函式將返回一個物件,但是不會立刻向下執行

ü  生成器中__iter__()和__next__()方法等是自動實現的,所以我們可以通過next()方法對物件進行迭代

ü  一旦函式被yield,函式會暫停,控制權返回呼叫者

ü  區域性變數和它們的狀態會被儲存,直到下一次呼叫

ü  函式終止的時候,StopIteraion會被自動丟擲

4)生成器函式構造示例

l  構造迴圈生成器

逆序yield出物件的元素

def a(my_str):

    length=len(my_str)

    for i in range(length-1,-1,-1):

        yield my_str[i]

 

for char in a("hello"):

    print(char)

 

l  生成器表示式

a=(x for x in range(10))

b=[x for x in range(10)]

# 這是錯誤的,因為生成器不能直接給出長度

# print("length a:",len(a))

 

# 輸出列表的長度

print("length b:",len(b))

 

b=iter(b)

# 二者輸出等價,不過b是在執行時開闢記憶體,而a是直接開闢記憶體

print(next(a))

print(next(b))