Python學習——迭代器&生成器&裝飾器


一、迭代器

      迭代器是訪問集合元素的一種方式。迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。迭代器只能往前不會后退迭代器的一大優點是不要求事先准備好整個迭代過程中所有的元素。迭代器僅僅在迭代到某個元素時才計算該元素,而在這之前或之后,元素可以不存在或者被銷毀。這個特點使得它特別適合用於遍歷一些巨大的或是無限的集合

特點:

  1. 訪問者不需要關心迭代器內部的結構,僅需通過next()方法不斷去取下一個內容
  2. 不能隨機訪問集合中的某個值 ,只能從頭到尾依次訪問
  3. 訪問到一半時不能往回退
  4. 便於循環比較大的數據集合,節省內存

生成一個迭代器:

 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 日志添加成功

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM