1. 程式人生 > >迭代器、生成器、裝飾器學習總結

迭代器、生成器、裝飾器學習總結

一、迭代器:

1、什麼是迭代器?

      在python中,迭代器是一個可以記住遍歷位置的物件,迭代器物件從集合的第一個元素開始訪問,直到所有的元素都被訪問完,迭代器只能往前不會後退。簡單來講我們見的比較多的是for 迴圈來遍歷列表、元組、字串等容器,這個就是迭代器的使用,所以說,迭代器簡單可以理解成我們平時要從櫃子裡取東西時的動作。

2、兩個內建迭代器協議方法:

 a、方法iter():返回物件本身,是for迴圈語句使用迭代器的要求。

 b、方法next():用於返回容器中下一個元素(所謂容器,簡單理解就是一個儲存東西的櫃子,要用的話,就可以拿出來,在python 中我們使用for語句來迴圈遍歷來取出使用)或者資料,當使用完容器中的資料時就會引發StopIteration錯誤。

3、建立並使用迭代器:

 1 class Use:    #定義了迭代器類
 2     def __init__(self,x=2,max=50):        #定義構造方法
 3         self.__mul,self.__x=x,x      #初始化私有的例項屬性
 4         self.__max=max
 5     def __iter__(self):       #定義迭代器協議方法
 6         return self           #返回類的自身
 7     def __next__(self):       #定義迭代器協議方法
 8         if self.__x and self.__x != 1:
 9           self.__mul  *= self.__x
10           if self.__mul <= self.__max:
11               return self.__mul
12           else:
13               raise StopIteration
14         else:
15              raise StopIteration
16 
17 if __name__ == '__main__':
18     my=Use()
19     for i in my:
20         print(i)
21 
22             

注意:當在python 中使用迭代器類時,一定要在某個條件下引發StopIteration錯誤,這樣可以結束遍歷迴圈,否則會產生死迴圈

4、使用內建迭代器方法iter():

a、iter(iterable),只有一個引數iterable,要求引數為可迭代的型別,也可以使用各種序列型別,演示如下;

list=[1,2,3,4]
it = iter(list)  #建立迭代器物件
for i in it:     #遍歷 迭代器中的資料
    print(i)     #顯示迭代效果

b、iter(callable,sentinel),第一個引數callable表示可呼叫型別,一般為函式;第二引數sentine是一個標記,當第一個引數(函式)的返回值等於第二個引數的值時,迭代或者遍歷會馬上停止。演示如下:

class Count:    #定義類Count
    def __init__(self,x=0):   # 定義構造方法
        self.x=x
count = Count()
def use_iter():
    count.x +=2
    return count.x
for i in iter(use_iter,12):    #通過迭代遍歷方法iter()產生的迭代器
    print(i)

5、方法next()的使用:

string='i like it'
it = iter(string)
while True:
    try:
        each=next(it) #讀取字元中的每一個元素,並使用try  except 結構來檢查是否有異常發生,當try裡面出現異常時,就會執行下面的except的語句
    except StopIteration:
        break
    print(each)

二、生成器:

1、什麼是生成器?

      在python 中,使用關鍵字yield定義的函式就稱為生成器,通過使用生成器,可以生成一個值序列為用於迭代,並且這個值序列不是一次生成的,而是使用一個,再生成一個,最大的好處是可以使程式節約大量的記憶體。

2、生成器的執行機制:

     在python程式中,生成器是一個記住上一次返回時在函式體中位置的函式,。對生成器函式的第二次(或第n次)呼叫,跳轉至該函式中間,而上次呼叫的所有佈局變數都保持不變。生成器不僅記住了它的資料狀態,還記住了它在流控制構造(在指令式程式設計中,這種構造不只是資料值)的中的位置。

     生成器的特點如下:

           a、生成器是一個函式,而且函式的引數都會保留

           b、當迭代到下一次呼叫時,所使用的引數都是第一次所保留的。也就是說,在整個函式呼叫中的引數都是第一次所呼叫時保留的,而不是新建立的

      在python程式中,使用關鍵字yield定義生成器。當向生成器索要一個數時,生成器就會執行。直至出現yield語句時,生成器才把yield的引數傳給你,之後生成器就不會往下繼續執行。當向生成器索要一個數時,它會從上次的狀態開始執行,直至出現yield語句時,才把引數傳給你,然後停下,如此反覆,直至退出函式為止

3、使用yield生成器:

def fib(max):
    a,b = 1,1
    while a < max:
        yield a   #程式執行到這裡就不會往下繼續執行了,所以第一次a =1,b=1,當第二次遍歷函式時fib()時,a ,b 的值還是上次的值,而且會跳到這裡,然後執行到下面的語句
        a,b = b,a+b
for n in fib(15):
    print(n)     #這裡列印的值其實是a的值

執行結果:

1
1
2
3
5
8
13

說明:在Python中,當函式定義裡面使用了關鍵字yield,那麼這個函式就是一個生成器;它的執行會和其他普通的函式有很多不同,該函式返回的是一個物件,而不是像平常函式所用的return語句那樣,能得到結果。如果想取得值,還需要呼叫next()函式。  

4、建立生成器:

def haha(n):
    while n > 0:
        print('開始生成......')
        yield n #定義一個生成器
        print('完成一次......')
        n -=1
if __name__ == '__main__':     #當匯入模組時不執行,否則會執行下面的程式碼
    for i in haha(4):
        print('遍歷得到的值',i)
    print()
    tutu=haha(3)
    print('已經例項化生成器物件')
    tutu.__next__() #直接遍歷自己建立的生成器
    print('第二次呼叫__next__()方法')
    tutu.__next__()  #以手工方式獲取生成器產生的數值序列

執行結果:

開始生成......
遍歷得到的值 4
完成一次......
開始生成......
遍歷得到的值 3
完成一次......
開始生成......
遍歷得到的值 2
完成一次......
開始生成......
遍歷得到的值 1
完成一次......

已經例項化生成器物件
開始生成......
第二次呼叫__next__()方法
完成一次......
開始生成......

注意:生成器在例項化時,不會立即執行,而是等候其呼叫方法__next__()才開始執行。

三、裝飾器:

1、什麼是裝飾器?

      在python程式中,通過使用裝飾器可以給函式或類增強功能,並且還可以快速地給不同的函式或類插入相同的功能,也就是說,裝飾器是一種實現程式碼的實現方式

2、建立裝飾器

      要想在Python程式中使用裝飾器,需要使用一個特殊的符號 "@" 來實現。在定義裝飾器裝飾函式時或類時,使用"@裝飾器名稱"的形式將符號 “@”放在函式或類的定義行之前。例如,有一個裝飾器名稱為"haha",當需要在函式中使用裝飾器功能時,可以使用如下形式定義這個函式:

                    @  haha

                     def tutu():

                           pass

       在pytnon程式中使用裝飾器後,上面的程式碼定義的函式tutu()可以只定義自己所需的功能,而裝飾器所定義的功能會自動插入到函式中去,這樣就可以節省大量具有相同功能的函式或類的程式碼。

3、使用裝飾器 裝飾函式:

def zz(fun):    #定義一個裝飾器函式
    def hh(*args,**bian):  #這裡第一個引數表示把args這個引數打包或者解包,第個引數是把傳輸進來的實參進行打包成字典的形
        print('開始執行...')
        fun(*args,**bian)    #使用被裝飾函式
        print("執行結束。。。。")
    return hh
@zz      #裝飾函式語句
def demo(x):   #定義普通函式,它被裝飾器裝飾
    a=[]       #定義空列表
    for i in range(x):
        a.append(i)    #將i新增到列表末尾
    print(a)
@zz
def hello(name):
    print('hello',name)
if __name__ == '__main__':
    demo(5)
    print()
    hello('haha')

執行結果:

開始執行...
[0, 1, 2, 3, 4]
執行結束。。。。

開始執行...
hello haha
執行結束。。。。

總結:當一般函式被裝飾器修飾時,會把裝飾器函式的功能插入到普通函式中去。

4、使用裝飾器修飾類:

def zz(myclass):    # 定義一個能夠裝飾類的裝飾器zz
    class Haha:
        #定義一個內嵌類Haha來代替被裝飾的類
        def __init__(self,z=0):
            self.z=0
            self.haha=myclass()
            #例項化被修飾的類
        def tutu(self):
            self.haha.tutu()
            print('z軸的座標:',self.z)
    return Haha
@zz
class Hoho:
    def __init__(self,x=0,y=0):
        self.x=0
        self.y=0
    def tutu(self):
        print('x軸的座標:',self.x)
        print('y軸的座標:',self.y)
if __name__ == '__main__':
    coor=Hoho()
    coor.tutu()

執行結果:

x軸的座標: 0
y軸的座標: 0
z軸的座標: 0

總結:用裝飾器修飾類,和修飾函式類似,只是在建立裝飾器裡函式返回的型別不同而已。

&n