Python學習——迭代器&產生器&裝飾器,python學習
一、迭代器
迭代器是訪問集合元素的一種方式。迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。迭代器只能往前不會後退迭代器的一大優點是不要求事先準備好整個迭代過程中所有的元素。迭代器僅僅在迭代到某個元素時才計算該元素,而在這之前或之後,元素可以不存在或者被銷毀。這個特點使得它特別適合用於遍曆一些巨大的或是無限的集合
特點:
產生一個迭代器:
1 >>> a= iter([1,2,3,4,5]) 2 >>> a 3 <list_iterator object at 0x0044ADF0> 4 5 >>> a.__next__() 6 1 7 >>> a.__next__() 8 2 9 >>> a.__next__()10 3
二、產生器
一個函數調用時返回一個迭代器,那這個函數就叫做產生器(generator),如果函數中包含yield文法,那這個函數就會變成產生器
代碼:
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 ''' 4 # @time : 2017/4/22 1:00 5 # @author : huange 6 # @version : 1.1 7 # @file : test2.py 8 # @Software: PyCharm 9 '''10 11 def out_money(totle):12 13 while totle > 0:14 15 totle -= 116 17 yield 1 # yield 返回一個值18 19 20 ATM = out_money(3)21 22 print("取到錢 %s 萬" % ATM.__next__())23 24 print("花掉花掉!")25 26 print("取到錢 %s 萬" % ATM.__next__())27 28 print("花掉花掉!")29 30 print("取到錢 %s 萬" % ATM.__next__())31 32 print("花掉花掉!")33 34 print("取到錢 %s 萬" % ATM.__next__()) # 到這時錢就取沒了,再取就報錯了35 36 print("取到錢 %s 萬" % ATM.__next__())
這個yield的主要效果呢,就是可以使函數中斷,並儲存中斷狀態,中斷後,代碼可以繼續往下執行,過一段時間還可以再重新調用這個函數,從上次yield的下一句開始執行。
可以通過yield實現在單線程的情況下實現並發運算效果
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 ''' 4 # @time : 2017/4/22 1:00 5 # @author : huange 6 # @version : 1.1 7 # @file : test2.py 8 # @Software: PyCharm 9 '''10 11 import time12 13 def consumer(name):14 print("%s 準備吃包子了!" %name)15 while True:16 baozi = yield # yield 通過 send()方法接收值17 print("包子[%s]來了,被[%s]吃了" %(baozi,name))18 19 def producer(name):20 c1 = consumer('A')21 c2 = consumer('B')22 c3 = consumer('C')23 24 c1.__next__()25 c2.__next__()26 c3.__next__()27 28 print("%s 開始準備做包子了!" % name)29 30 for i in range(10):31 time.sleep(1)32 print('做了3個包子')33 c1.send(i)34 c2.send(i)35 c3.send(i)36 37 producer('hh')
三、裝飾器
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 ''' 4 # @time : 2017/4/24 20:29 5 # @author : huange 6 # @version : 1.1 7 # @file : 裝飾器.py 8 # @Software: PyCharm 9 '''10 11 # @login內部會執行一下操作:12 # 1.執行login函數,並將 @login 下面的 函數 作為login函數的參數,即:@login 等價於 login(movie)13 # 2.•將執行完的 login 函數傳回值賦值給@login下面的函數的函數名14 15 def login(func):16 def inner(*args,**kwargs):17 print("login success...")18 return func(*args,**kwargs)19 return inner20 21 def home():22 print("welcome to Home...")23 24 25 @login26 def movie(name,passwd):27 print("welcome [%s] [%s] to movie...." % (name,passwd))28 29 @login30 def music(name):31 print("welcome [%s] to music..." % name)32 33 movie('huhuan','123')34 music('huhuan')35 home()
如上所示:被裝飾的函數帶有不同個數的參數,因此,裝飾器需要用到動態參數!
一個函數可以被多個裝飾器裝飾:
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 ''' 4 # @time : 2017/4/24 20:29 5 # @author : huange 6 # @version : 1.1 7 # @file : 裝飾器.py 8 # @Software: PyCharm 9 '''10 # 驗證登陸11 def login(func):12 def inner(*args,**kwargs):13 print("login success...")14 return func(*args,**kwargs)15 return inner16 17 # 驗證是否是會員使用者18 def member(func):19 def inner(*args,**kwargs):20 print("welcome member...")21 return func(*args,**kwargs)22 return inner23 24 def home():25 print("welcome to Home...")26 27 # @login內部會執行一下操作:28 # 1.執行login函數,並將 @login 下面的 函數 作為login函數的參數,即:@login 等價於 login(movie)29 # 2.•將執行完的 login 函數傳回值賦值給@login下面的函數的函數名30 @login31 @member32 def movie(name,passwd):33 print("welcome [%s] [%s] to movie...." % (name,passwd))34 35 @member36 @login37 def music(name):38 print("welcome [%s] to music..." % name)39 40 movie('huhuan','123')41 music('huhuan')42 home()
裝飾器中帶有參數:
1 # 認證函數 2 def auth(request,kargs): 3 print("認證成功!") 4 # 日誌函數 5 def log(request,kargs): 6 print("日誌添加成功") 7 # 裝飾器函數。接收兩個參數,這兩個參數應該是某個函數的名字。 8 def Filter(auth_func,log_func): 9 # 第一層封裝,f1函數實際上被傳遞給了main_fuc這個參數10 def outer(main_func):11 # 第二層封裝,auth和log函數的參數值被傳遞到了這裡12 def wrapper(request,kargs):13 # 下面代碼的判斷邏輯不重要,重要的是參數的引用和傳回值14 before_result = auth(request,kargs)15 if(before_result != None):16 return before_result;17 18 main_result = main_func(request,kargs) #需要裝飾的函數19 if(main_result != None):20 return main_result;21 22 after_result = log(request,kargs)23 if(after_result != None):24 return after_result;25 26 return wrapper27 return outer28 # 注意了,這裡的裝飾器函數有參數,它的意思是先執行filter函數29 # 然後將filter函數的傳回值作為裝飾器函數的名字返回到這裡,所以,30 # 其實這裡,Filter(auth,log) = outer , @Filter(auth,log) = @outer31 @Filter(auth,log)32 def f1(name,age):33 34 print("%s 正在串連業務部門1資料介面......"%name)35 36 # 調用方法37 f1("jack",18)38 39 結果:40 認證成功!41 jack 正在串連業務部門1資料介面......42 日誌添加成功