【十】叠代器、生成器、裝飾器和標準庫
阿新 • • 發佈:2017-07-28
ber 遍歷 mmu 取出 out most 例如 list char
一:叠代器
在python中,很多對象可以直接通過for語句來直接遍歷,例如:list、string、dict等等,這些被稱為可叠代對象
叠代器是一個可以I記住遍歷的位置的對象。
在python中,支持叠代器協議的就是實現對象的iter()和next()方法。
- iter()方法返回叠代器本身
- next()方法返回容器的下一個元素
- 在結尾時引發stopiteration異常
叠代器有兩個基本的方法:__iter__()和next()方法,一個用來獲取叠代器對象,一個用來獲取容器中的下一個元素
In [1]: l=[1,2,3,4,54] In [2]: it=iter(l) #通過iter()方法獲得了list的叠代對象In [3]: it Out[3]: <list_iterator at 0x7f4242c89e10> #通過next方法獲取下一個元素 In [4]: next(it) Out[4]: 1 In [5]: next(it) Out[5]: 2 In [6]: next(it) Out[6]: 3 In [7]: next(it) Out[7]: 4 In [8]: next(it) Out[8]: 54 #當容器中沒有可訪問的元素後,拋出stopiteration異常 In [9]: next(it) --------------------------------------------------------------------------- StopIteration Traceback (most recent call last)<ipython-input-9-2cdb14c0d4d6> in <module>() ----> 1 next(it) StopIteration:
其實,當我們使用for語句的時候,for語句會自動通過iter()方法來獲得叠代對象,並通過next()方法獲取下一個元素
二:生成器
生成器是用來創建python序列的一個對象,使用它可以叠代龐大的序列,且不需要在內存中創建和儲存整個序列
#range生成器 In [10]: sum(range(1,101)) Out[10]: 5050
每次叠代生成器,它都會記錄上一次調用的位置,並且返回下一個值
生成器函數和普通函數類似,但是他的返回值使用yield語句聲明,而不是return
生成器是為叠代器產生數據的。
In [14]: def my_range(first=0,last=10,step=1): ...: number=first ...: while number<last: ...: yield number ...: number+=step ...: #這是一個普通的函數 >>> my_range <function my_range at 0x1070c4e18> #返回的是一個生成器對象 In [15]: my_range() Out[15]: <generator object my_range at 0x7f4241b83fc0> #對這個生成器對象進行叠代 In [16]: ranger=my_range(1,5) In [17]: for i in ranger: ...: print(i) ...: 1 2 3 4 In [18]: print(ranger) <generator object my_range at 0x7f424291ea40> #在調用生成器運行的過程中,每次遇到 yield 時函數會暫停並保存當前所有的運行信息,返回yield的值。並在下一次執行 next()方法時從當前位置繼續運行。 In [19]: list(ranger) Out[19]: []#因為yield是記住位置的,ranger只裏面的內容在for叠代已經全部取出來了,所以這裏面為空 In [20]: ranger=my_range(1,5) #還沒有進行叠代,所以數據都還存在 In [21]: list(ranger) Out[21]: [1, 2, 3, 4]
習題:使用生成器寫一個斐波納挈數列
In [24]: def shulie(): ...: num=int(input("請輸入一個整數")) ...: f1=0 ...: f2=1 ...: if num<=0: ...: print("請輸入一個正整數") ...: elif num==1: ...: print("斐波納挈數列:%d"%f1) ...: else: ...: print("斐波納挈:",end="") ...: for n in range(1,num-1): ...: f=f1+f2 ...: f1,f2=f2,f ...: print(f,end="") ...: In [25]: shulie() 請輸入一個整數0 請輸入一個正整數 In [26]: shulie() 請輸入一個整數1 斐波納挈數列:0 #輸出前10項的斐波納挈數列 In [29]: shulie() 請輸入一個整數10 斐波納挈:12358132134
三:裝飾器
1.args和*kwargs
In [46]: def x(*args,**kwargs): ...: print(args) #輸出參數的時候不需要加* ...: print(kwargs) ...: #從如下例子可以看出,*args就是一個列表,**kwargs就是一個字典 In [47]: x(1,2,3) (1, 2, 3) {} In [49]: x(1,2,3,one=1,two=2) (1, 2, 3) {‘two‘: 2, ‘one‘: 1} In [50]: x(one=1,two=2) () {‘two‘: 2, ‘one‘: 1}
2.閉包
In [51]: def foo(x,y): #x,y為自由變量 ...: def bar(): ...: a=4 ...: return x+y+a ...: return bar ...: In [52]: bar=foo(1,2) In [53]: bar Out[53]: <function __main__.foo.<locals>.bar> In [54]: bar() Out[54]: 7
3.作為參數的函數
函數document_it()定義了一個裝飾器,需實現如下功能:
- 打印輸出函數的名字和參數值
- 執行含有參數的函數
- 打印輸出結果
- 返回修改後的函數
#裝飾器 In [75]: def documenyt_it(func): ...: def new_func(*args,**kwargs): ...: print("func name",func.__name__) ...: print("args",args) ...: print("kwargs",kwargs) ...: result=func(*args,**kwargs) ...: print("result",result) ...: return result ...: return new_func ...: In [76]: def add(a,b): ...: return a+b ...: In [77]: add(3,5) Out[77]: 8 In [78]: test_add=documenyt_it(add) #人工對裝飾器賦值 In [79]: test_add(3,5) func name add args (3, 5) kwargs {} result 8 Out[79]: 8
#自己設定裝飾器
#coding=utf-8 def document_it(func): def new_func(*args,**kwargs): print(‘func name‘,func.__name__) print(‘args‘,args) print(‘keyword args‘,kwargs) result=func(*args,**kwargs) print(‘result‘,result) return result return new_func def square_it(func): def new_function(*args,**kwargs): result=func(*args,**kwargs) return result*result return new_function @square_it #裝飾器 @document_it def add(a,b): return a+b #註意:打印結果:函數越靠近哪個裝飾器就執行那個裝飾器內的數據 print(add(3,5)) #add=add(sqare_it(document_it(add)))
打印結果:
C:\Python27\python.exe "D:/PyCharm Community Edition 5.0.3/代碼/ex89.py" (‘func name‘, ‘add‘) (‘args‘, (3, 5)) (‘keyword args‘, {}) (‘result‘, 8) 64 Process finished with exit code 0
【十】叠代器、生成器、裝飾器和標準庫