一、迭代器
迭代器是訪問集合元素的一種方式。迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。迭代器只能往前不會后退迭代器的一大優點是不要求事先准備好整個迭代過程中所有的元素。迭代器僅僅在迭代到某個元素時才計算該元素,而在這之前或之后,元素可以不存在或者被銷毀。這個特點使得它特別適合用於遍歷一些巨大的或是無限的集合
特點:
- 訪問者不需要關心迭代器內部的結構,僅需通過next()方法不斷去取下一個內容
- 不能隨機訪問集合中的某個值 ,只能從頭到尾依次訪問
- 訪問到一半時不能往回退
- 便於循環比較大的數據集合,節省內存
生成一個迭代器:
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 -= 1 16 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 time 12 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 inner 20 21 def home(): 22 print("welcome to Home...") 23 24 25 @login 26 def movie(name,passwd): 27 print("welcome [%s] [%s] to movie...." % (name,passwd)) 28 29 @login 30 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 inner 16 17 # 驗證是否是會員用戶 18 def member(func): 19 def inner(*args,**kwargs): 20 print("welcome member...") 21 return func(*args,**kwargs) 22 return inner 23 24 def home(): 25 print("welcome to Home...") 26 27 # @login內部會執行一下操作: 28 # 1.執行login函數,並將 @login 下面的 函數 作為login函數的參數,即:@login 等價於 login(movie) 29 # 2.•將執行完的 login 函數返回值賦值給@login下面的函數的函數名 30 @login 31 @member 32 def movie(name,passwd): 33 print("welcome [%s] [%s] to movie...." % (name,passwd)) 34 35 @member 36 @login 37 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 wrapper 27 return outer 28 # 注意了,這里的裝飾器函數有參數,它的意思是先執行filter函數 29 # 然后將filter函數的返回值作為裝飾器函數的名字返回到這里,所以, 30 # 其實這里,Filter(auth,log) = outer , @Filter(auth,log) = @outer 31 @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 日志添加成功