迭代器、生成器、裝飾器學習總結
一、迭代器:
1、什麼是迭代器?
在python中,迭代器是一個可以記住遍歷位置的物件,迭代器物件從集合的第一個元素開始訪問,直到所有的元素都被訪問完,迭代器只能往前不會後退。簡單來講我們見的比較多的是for 迴圈來遍歷列表、元組、字串等容器,這個就是迭代器的使用,所以說,迭代器簡單可以理解成我們平時要從櫃子裡取東西時的動作。
2、兩個內建迭代器協議方法:
a、方法iter():返回物件本身,是for迴圈語句使用迭代器的要求。
b、方法next():用於返回容器中下一個元素(所謂容器,簡單理解就是一個儲存東西的櫃子,要用的話,就可以拿出來,在python 中我們使用for語句來迴圈遍歷來取出使用)或者資料,當使用完容器中的資料時就會引發StopIteration錯誤。
3、建立並使用迭代器:
1 class Use: #定義了迭代器類 2 def __init__(self,x=2,max=50): #定義構造方法 3 self.__mul,self.__x=x,x #初始化私有的例項屬性 4 self.__max=max 5 def __iter__(self): #定義迭代器協議方法 6 return self #返回類的自身 7 def __next__(self): #定義迭代器協議方法 8 if self.__x and self.__x != 1: 9 self.__mul *= self.__x 10 if self.__mul <= self.__max: 11 return self.__mul 12 else: 13 raise StopIteration 14 else: 15 raise StopIteration 16 17 if __name__ == '__main__': 18 my=Use() 19 for i in my: 20 print(i) 21 22
注意:當在python 中使用迭代器類時,一定要在某個條件下引發StopIteration錯誤,這樣可以結束遍歷迴圈,否則會產生死迴圈
4、使用內建迭代器方法iter():
a、iter(iterable),只有一個引數iterable,要求引數為可迭代的型別,也可以使用各種序列型別,演示如下;
list=[1,2,3,4] it = iter(list) #建立迭代器物件 for i in it: #遍歷 迭代器中的資料 print(i) #顯示迭代效果
b、iter(callable,sentinel),第一個引數callable表示可呼叫型別,一般為函式;第二引數sentine是一個標記,當第一個引數(函式)的返回值等於第二個引數的值時,迭代或者遍歷會馬上停止。演示如下:
class Count: #定義類Count def __init__(self,x=0): # 定義構造方法 self.x=x count = Count() def use_iter(): count.x +=2 return count.x for i in iter(use_iter,12): #通過迭代遍歷方法iter()產生的迭代器 print(i)
5、方法next()的使用:
string='i like it' it = iter(string) while True: try: each=next(it) #讀取字元中的每一個元素,並使用try except 結構來檢查是否有異常發生,當try裡面出現異常時,就會執行下面的except的語句 except StopIteration: break print(each)
二、生成器:
1、什麼是生成器?
在python 中,使用關鍵字yield定義的函式就稱為生成器,通過使用生成器,可以生成一個值序列為用於迭代,並且這個值序列不是一次生成的,而是使用一個,再生成一個,最大的好處是可以使程式節約大量的記憶體。
2、生成器的執行機制:
在python程式中,生成器是一個記住上一次返回時在函式體中位置的函式,。對生成器函式的第二次(或第n次)呼叫,跳轉至該函式中間,而上次呼叫的所有佈局變數都保持不變。生成器不僅記住了它的資料狀態,還記住了它在流控制構造(在指令式程式設計中,這種構造不只是資料值)的中的位置。
生成器的特點如下:
a、生成器是一個函式,而且函式的引數都會保留
b、當迭代到下一次呼叫時,所使用的引數都是第一次所保留的。也就是說,在整個函式呼叫中的引數都是第一次所呼叫時保留的,而不是新建立的
在python程式中,使用關鍵字yield定義生成器。當向生成器索要一個數時,生成器就會執行。直至出現yield語句時,生成器才把yield的引數傳給你,之後生成器就不會往下繼續執行。當向生成器索要一個數時,它會從上次的狀態開始執行,直至出現yield語句時,才把引數傳給你,然後停下,如此反覆,直至退出函式為止
3、使用yield生成器:
def fib(max): a,b = 1,1 while a < max: yield a #程式執行到這裡就不會往下繼續執行了,所以第一次a =1,b=1,當第二次遍歷函式時fib()時,a ,b 的值還是上次的值,而且會跳到這裡,然後執行到下面的語句 a,b = b,a+b for n in fib(15): print(n) #這裡列印的值其實是a的值
執行結果:
1 1 2 3 5 8 13
說明:在Python中,當函式定義裡面使用了關鍵字yield,那麼這個函式就是一個生成器;它的執行會和其他普通的函式有很多不同,該函式返回的是一個物件,而不是像平常函式所用的return語句那樣,能得到結果。如果想取得值,還需要呼叫next()函式。
4、建立生成器:
def haha(n): while n > 0: print('開始生成......') yield n #定義一個生成器 print('完成一次......') n -=1 if __name__ == '__main__': #當匯入模組時不執行,否則會執行下面的程式碼 for i in haha(4): print('遍歷得到的值',i) print() tutu=haha(3) print('已經例項化生成器物件') tutu.__next__() #直接遍歷自己建立的生成器 print('第二次呼叫__next__()方法') tutu.__next__() #以手工方式獲取生成器產生的數值序列
執行結果:
開始生成...... 遍歷得到的值 4 完成一次...... 開始生成...... 遍歷得到的值 3 完成一次...... 開始生成...... 遍歷得到的值 2 完成一次...... 開始生成...... 遍歷得到的值 1 完成一次...... 已經例項化生成器物件 開始生成...... 第二次呼叫__next__()方法 完成一次...... 開始生成......
注意:生成器在例項化時,不會立即執行,而是等候其呼叫方法__next__()才開始執行。
三、裝飾器:
1、什麼是裝飾器?
在python程式中,通過使用裝飾器可以給函式或類增強功能,並且還可以快速地給不同的函式或類插入相同的功能,也就是說,裝飾器是一種實現程式碼的實現方式
2、建立裝飾器
要想在Python程式中使用裝飾器,需要使用一個特殊的符號 "@" 來實現。在定義裝飾器裝飾函式時或類時,使用"@裝飾器名稱"的形式將符號 “@”放在函式或類的定義行之前。例如,有一個裝飾器名稱為"haha",當需要在函式中使用裝飾器功能時,可以使用如下形式定義這個函式:
@ haha
def tutu():
pass
在pytnon程式中使用裝飾器後,上面的程式碼定義的函式tutu()可以只定義自己所需的功能,而裝飾器所定義的功能會自動插入到函式中去,這樣就可以節省大量具有相同功能的函式或類的程式碼。
3、使用裝飾器 裝飾函式:
def zz(fun): #定義一個裝飾器函式 def hh(*args,**bian): #這裡第一個引數表示把args這個引數打包或者解包,第個引數是把傳輸進來的實參進行打包成字典的形 print('開始執行...') fun(*args,**bian) #使用被裝飾函式 print("執行結束。。。。") return hh @zz #裝飾函式語句 def demo(x): #定義普通函式,它被裝飾器裝飾 a=[] #定義空列表 for i in range(x): a.append(i) #將i新增到列表末尾 print(a) @zz def hello(name): print('hello',name) if __name__ == '__main__': demo(5) print() hello('haha')
執行結果:
開始執行... [0, 1, 2, 3, 4] 執行結束。。。。 開始執行... hello haha 執行結束。。。。
總結:當一般函式被裝飾器修飾時,會把裝飾器函式的功能插入到普通函式中去。
4、使用裝飾器修飾類:
def zz(myclass): # 定義一個能夠裝飾類的裝飾器zz class Haha: #定義一個內嵌類Haha來代替被裝飾的類 def __init__(self,z=0): self.z=0 self.haha=myclass() #例項化被修飾的類 def tutu(self): self.haha.tutu() print('z軸的座標:',self.z) return Haha @zz class Hoho: def __init__(self,x=0,y=0): self.x=0 self.y=0 def tutu(self): print('x軸的座標:',self.x) print('y軸的座標:',self.y) if __name__ == '__main__': coor=Hoho() coor.tutu()
執行結果:
x軸的座標: 0 y軸的座標: 0 z軸的座標: 0
總結:用裝飾器修飾類,和修飾函式類似,只是在建立裝飾器裡函式返回的型別不同而已。
&n