1. 程式人生 > >【十】叠代器、生成器、裝飾器和標準庫

【十】叠代器、生成器、裝飾器和標準庫

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

【十】叠代器、生成器、裝飾器和標準庫