一、迭代器
迭代協議:對象必須提供一個next方法,執行該方法后會返回迭代的下一項或者拋出Stopiteration異常,終止迭代。切只能往前,不能倒退。
可迭代對象:遵循迭代協議的對象就是可迭代對象。
迭代器是一個可以記住遍歷的位置的對象。迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。迭代器只能往前不會后退。
迭代器有兩個基本的方法:iter() 和 next()。
字符串,列表或元組對象都可用於創建迭代器,生成迭代器的方法是iter():
1 li = [1,2,3,4] 2 #inter()本質調用了內置的__iter__ 3 a = li.__iter__() #生產一個可迭代對象 4 #next()本質調用__next__() 5 a.__next__() #對可迭代對象進行取值
方法二:
>>li = [1,2,3,4,5] >>it = iter(li) #生成一個迭代器 >>it.__next__() 1 >>next(it) #以上兩種next都可以使用 2 >>for i in it: print(i) 3 4 5 #迭代完畢后,迭代器里面的數據就沒有了 >> type(it) <class 'list_iterator'> #類型是迭代器類型
二、生成器
在描述生成器前我們先來了解列表生成式:
#普通定義的列表直接把列表寫死 li = [1,2,3,4,5] #使用列表生成式,可以為列表添加一些新的屬性 li1 = [a*a for a in range(10)] print(li1) #也可以用以下兩種方法方法 li2 = list(map(lambda x:x+1,li)) print(li2) a = [] for i in range(10): a.append(i+1) print(a) #從以上對比可以看出,使用第二種方法代碼最為簡單,即列表生成式
雖然有列表生成式,可以簡化生成特定列表的操作,但是當列表數據過大,就會過度的消耗內存,並且列表是數據也不會一直使用,在python中有一種一邊循環一邊計算的機制就是生成器。
生成器的第一種表現形式:
#創建一個生成器 li = (a*a for a in range(10)) print(li) #<generator object <genexpr> at 0x00000000027BD468>,返回一個生成器對象,用next調用對象 print(li.__next__()) print(next(li)) #且只能調用一次,不能往回調用 '''我們講過,generator保存的是算法,每次調用next(g), 就計算出g的下一個元素的值,直到計算到最后一個元素,沒有更多的元素時, 拋出StopIteration的錯誤。一般情況下,我們用for循環來調用全部數據''' for i in li: print(i)
生成器的第二種表現形式:
生成器:一個函數調用時返回一個迭代器,那這個函數就叫做生成器(generator),如果函數中包含yield語法,那這個函數就會變成生成器 跟普通函數不同的是,生成器是一個返回迭代器的函數,只能用於迭代操作,更簡單點理解生成器就是一個迭代器。調用一個生成器函數,返回的是一個迭代器對象。
yield語法:每當行數運行到yield是就會中斷並且保存當前所有的運行信息,並且在執行next()方法后繼續從中斷的地方運行。
#生成一個斐波拉契數列 def fib(max): a,b,n = 0,0,1 while n < max: a, b = b,a+b n +=1 return 'done' c = fib(5) print(c) #弊端,會直接全部生成 #把該函數變為一個生成器 def fib2(max): a,b,n = 0,0,1 while n < max: yield b #遇到一次返回一次,再次激活則運行后面的代碼,用next激活 a, b = b,a+b n +=1 d = fib2(5) print(next(d))
下面是一個利用yield實現的一種單線程下的並發效果,也可以理解為一協程(后面會講這一內容):
import time def consumer(name): print('%s准備吃包子了!' % name) while True: baozi = yield # 保存當前狀態的值,並且退出函數 print('包子[%s]來了,被[%s]吃了!'% (baozi,name)) # c = consumer('alix') 生成一個生成器對象 # c.__next__() 調用生成器 def producer(): c = consumer('a') c2 = consumer('b') c.__next__() c2.__next__() print('老子開始准備做包子了') for i in range(10): time.sleep(1) print('做了1個包子,分兩半') c.send(i) #給yield傳值,並且喚醒yield c2.send(i) producer()
三、裝飾器
裝飾器:本質上就是函數,作用就是為其他函數添加其他功能
原則:1、不能修改被裝飾的函數的源代碼
2、不能修改被修飾函數的調用方式
在將裝飾器前我們進行一些裝飾器的知識儲備:
1.函數即'變量'
2.高階函數
1.把一個函數名當做實參傳給另一個函數(添加功能不修改函數的源代碼)
2.返回值中包含函數名(不修改函數的調用方式)
3.嵌套函數
函數即“變量”:
函數定義好后就像變量一樣存儲在內存中,當我們去調用的時候才會有意義。
#函數即變量 # def foo(): # print('in the foo') # foo() #即無需考慮函數的定義順序,就和定義變量一樣 def bar(): print('in the bar') def foo(): print('in the foo') bar() foo()
高階函數:即把一個函數名當做實參傳遞給函數,就類似有把一個變量名傳遞給函數。
# 高階函數:把一個函數名,當做實參傳給函數 import time def bar(): time.sleep(3) #暫停3秒 print('in the bar') def text1(fun): start_time = time.time() #起始時間 fun() stop_time = time.time() #結束時間 print('the fun time is %s' % (stop_time-start_time)) #計算出fun()所用的時間 text1(bar) #將該函數名傳遞進去 def bar2(): time.sleep(3) print('in the bar2') def text2(fun): print(fun) return fun bar2 = text2(bar2) bar2()
通過高階函數的作用可以看出:在不改變函數的源代碼的情況下,給函數增加了計時的功能
嵌套函數:
def foo(): print('in the foo') def bar(): print('in the bar') bar() foo()
結合以上三種實現裝飾器:
import time def timer(func): #timer(text1) func=text1 裝飾器函數 def wrapper(*args,**kwargs): start_time = time.time() func() #run text1 stop_time = time.time() print('the fun run time is %s' % (stop_time-start_time)) return wrapper @timer # text1 = timer(text1) 這一步就是把text1傳入timer def text1(): time.sleep(1) print('the is text1') text1()
帶參數的裝飾器:
user,passwd = 'alex','1234' def auth(outh_type): print('auth func:',outh_type) def outh_wrapper(func): def wrapper(*args,**kwargs): print('wrapper func args:',*args,**kwargs) if outh_type == 'local': username = input('Username:'.strip()) password = input('Password:'.strip()) if user == username and passwd == password: print('\033[32;1mUser has passed authentication\033[0m') res = func(*args,*kwargs) print('-- after authentication') return res else: exit("\033[31;1mInvalid username or password\033[0m") elif outh_type == 'ldap': print('搞毛線') return wrapper return outh_wrapper @auth(outh_type='local') def index(): print('welcom to index page') index()
http://www.cnblogs.com/wupeiqi/articles/4980620.html
