python迭代器,生成器,裝飾器
一、迭代器
迭代器從表面上看是一個數據流物件或容器,當使用其中的資料時,每次從資料流中取一個數據,直到資料被取完,而且資料不會被重複使用
__iter__():
__next__():
"__iter__()"方法返回物件本身,它是for語句使用迭代器的要求
"__next__()"方法用於返回容器中下一個元素或資料,當容器中的資料用盡時,應該引發StopIteration異常
任何一個類,只要它實現了或具有這兩個方法,就可以稱其為迭代器,也可以說是迭代的。在使用它作為迭代器時,就可以用for來遍歷(迭代)它,示例程式碼如下
for item in iterator:
pass
每個迴圈中,for語句都會從迭代器的序列中取一個數據,並賦值給item,供迴圈內使用或處理。從形式上完全與遍歷元組,列表,字串,字典等序列一樣class
self.__mul,self.__x = x,x self.__xmax = xmax def __iter__(self): #定義迭代器協議方法,返回類自身 return self def __next__(self): #定義迭代器協議方法 if self.__mul and self.__x != 1: self.__mul *= self.__x if self.__mul <= self.__xmax: return self.__mul #返回值 else: raise StopIteration #引 StopIteration 錯誤 else:raise StopIteration if __name__ =='__main__': myiter = MyIterator() #例項化迭代器MyIterator for i in myiter: #遍歷並輸出值 print('迭代的資料元素為:',i)
#執行結果
迭代的資料元素為: 4
迭代的資料元素為: 8
迭代的資料元素為: 16
迭代的資料元素為: 32
迭代的資料元素為: 64
【程式碼說明】
從程式碼中可以看出,如果需要產生很大範圍的數的序列,採用列表或元組等進行一次性生成,則必須會佔據大量
的記憶體空間,對系統有很大的“殺傷力”。而使用了迭代器,則可以每次呼叫時生成一個,顯然可以節約大量的記憶體空間。
二、生成器
生成器物件是通過使用yield關鍵字定義的函式,因此,生成器也是一個函式。生成器用於生成一個值的序列,以便在迭代中使用
def myYield(n): #定義一個生成器(函式) while n < 5: print('start') yield n #yield這一步就開始返回n的值了,在進入下一步從print('one...')開始執行 print('one...') n += 1 if __name__ == '__main__': for i in myYield(1): #for迴圈遍歷生成器 print('遍歷得到的值:',i) print() my_yield = myYield(0) #生成一個生成物件 print('已經例項化生成器物件') print(my_yield.__next__()) #手工呼叫其特殊方法,獲取序列中一個值 print(my_yield.__next__()) #第二次手工呼叫,繼續輸出yield之後的輸出 #執行結果 start 遍歷得到的值: 1 one... start 遍歷得到的值: 2 one... start 遍歷得到的值: 3 one... start 遍歷得到的值: 4 one... 已經例項化生成器物件 start 0 one... start 1
【程式碼說明】
生成器中包含yield語句,可以用for直接遍歷,也可以手工呼叫其__next__()方法進行遍歷
yield語句是生成器中的關鍵語句,生成器在例項化時並不會立即執行,而是等待呼叫其__next__()方法才開始執行,並且當程式執行完yield語句後就會 “hold”,即保持其當前狀態且停止執行,等待下一次遍歷才恢復執行
生成器與協程
運用send()方法來重置生成器的生成序列,可以傳送數字字串等
def consumer(): #定義一個消費者模型(生成器協程) print('等待接收處理任務。。。') while True: data = (yield) print('收到任務:',data) #模擬接受並處理任務 #此處可以呼叫函式來完成任務 def producer(): #定義一個生產者模型 c =consumer() c.__next__() for i in range(3): print('傳送一個任務。。。','任務%d' %i) c.send(1) #傳送數字“1” c.send('任務%d' %i) #傳送字串 if __name__ == '__main__': producer() #呼叫函式producer #執行結果 等待接收處理任務。。。 傳送一個任務。。。 任務0 收到任務: 1 收到任務: 任務0 傳送一個任務。。。 任務1 收到任務: 1 收到任務: 任務1 傳送一個任務。。。 任務2 收到任務: 1 收到任務: 任務2
【程式碼說明】
程式碼中通過定義的兩個函式分別代表生成者和消費者模型,而其中的消費者模型實際是一個生成器。在生成者模型函式中每個迴圈模擬傳送一個任務給消費者模型(生成器),而生成器則可以呼叫相關函式來處理任務,這就是運用yield語句的“hold”性質來完成這一項任務
裝飾器: