python協程函數應用 列表產生式 產生器運算式

來源:互聯網
上載者:User

標籤:基礎   文法   區別   優點   迴圈   ken   應用   toolbar   rip   

一、知識點整理:

1、可迭代的:對象下有_iter_方法的都是可迭代的對象

 迭代器:對象._iter_()得到的結果就是迭代器
 迭代器的特性:
  迭代器._next_() 取下一個值

 優點:
  1.提供了一種統一的迭代對象的方式,不依賴於索引
  2.惰性計算
 缺點:
  1.無法擷取迭代器的長度
  2.一次性的,只能往後取值,不能往前退,不能像索引那樣去取得某個位置的值

2、產生器:函數內帶有yield關鍵字,那麼這個函數執行的結果就是產生器

  產生器的本質就是迭代器

def func():
n=0
  while True:
    yield n
    n+=1
g = func()
next(g)

3、總結yield的功能:
  1、相當於把_iter_和_next_方法封裝到函數內部
  2、與return比,return只能返回一次,而yield能返回多次
  3、函數暫停以及繼續啟動並執行狀態是通過yield儲存的

4、yield的運算式形式:  如:food = yield

def eater(name):
  print("%s start to eat"%name)
  while True:
    food = yield
    print("%s eat %s"%(name,food))
e = eater("zhejiangF4")
next(e)
e.send("aaa")  

5、e.send 與 next(e)的區別

#1.如果函數內yield是運算式形式,那麼必須先next(e)

#2.二者的共同之處是都可以讓函數在上一次暫停位置繼續運行,不一樣的地方在於send在觸發下一次代碼的執行時,會順便給yield傳一個值

二、產生器  協程函數的應用

1、編寫一個裝飾器,在不變更原代碼 協程函數 的基礎上,直接就能給主函數傳值!(協程函數第一步需要next()觸發,既將觸發寫入裝飾器中!)

 1 def f(func):  #定義裝飾器 2     def f1(*args,**kwargs): 3         res = func(*args,**kwargs) 4         next(res)  #觸發主函數 5         return res 6     return f1 7 @f 8 def eater(name):   #主函數 9     print("%s start to eat"%name)10     while True:11         food = yield12         print("%s eat %s"%(name,food))13 e  = eater("zhejiangF4")14 e.send("something")   #直接傳值

執行結果:

1 zhejiangF4 start to eat2 zhejiangF4 eat something

 ##在IDE上加上斷點,debug運行查看##

2、遞迴目錄,過濾檔案中帶有“python”內容的檔案,然後將這些檔案列印。此段代碼實現功能,牽扯到面向過程編程的思想!定義的每一個函數都是環環相扣,猶如一個完整的生產線一樣!

面向過程的編程思想:流水線式的編程思想,在設計程式時,需要把整個流程設計出來

#優點:
1、體繫結構更加清晰
2、簡化程式的複雜度
#缺點:
1、可擴充性極其的差,所以說面向過程的應用情境是:不需要經常變化的軟體。

 1 import os,time 2 def init(func): 3     def wrapper(*args,**kwargs): 4         res = func(*args,**kwargs) 5         next(res) 6         return res 7     return wrapper 8  9 @init10 def search(target):11     ‘找到檔案的絕對路徑‘12     while True:13         dir_name=yield14         #print(‘車間search開始生產產品:檔案的絕對路徑‘)15         time.sleep(1)16         g = os.walk(dir_name)17         for i in g:18             for j in i[-1]:19                 file_path = "%s\\%s"%(i[0],j)20                 target.send(file_path)21 @init22 def opener(target):23     ‘開啟檔案,擷取檔案控制代碼‘24     while True:25         file_path = yield26         #print(‘車間opener開始生產產品:檔案控制代碼‘)27         time.sleep(1)28         with open(file_path) as f:29             target.send((file_path,f))30 @init31 def cat(target):32     ‘讀取檔案內容‘33     while True:34         file_path,f = yield35         #print(‘車間cat開始生產產品:檔案的一行內容‘)36         time.sleep(1)37         for line in f:38             target.send((file_path,line))39 @init40 def grep(pattern,target):41     ‘過濾一行內容中有無python‘42     while True:43         file_path,line = yield44         #print(‘車間grep開始生產產品:包含python這一行內容的檔案路徑‘)45         time.sleep(0.2)46         if pattern in line:47             target.send(file_path)48 @init49 def printer():50     ‘列印檔案路徑‘51     while True:52         file_path = yield53         #print(‘車間printer開始生產產品:得到最終的產品‘)54         time.sleep(1)55         print(file_path)56 g = search(opener(cat(grep(‘python‘,printer()))))57 g.send(‘G:\\zhang‘)

 

執行結果:

1 G:\zhang\a3.txt2 G:\zhang\a1\a1.txt3 G:\zhang\a2\a2.txt

 

 

三、列表產生式

  1、由來

  在實際編程的情況中,我們常常需要產生一些列表。除了比較低效的用for迴圈來一個一個往列表中append外,另一個比較好的方法就是:

  python給我們提供了非常強大的建立列表的方式。

2、文法 
  [expression for item1 in iterable1 if condition1
       for item2 in iterable2 if condition2
   for item3 in iterable3 if condition3
   for itemN in iterableN if conditionN]
通俗的來講,列表產生式由三部分拼接組成:當然每次寫之前都應該先給出[],然後在裡邊添加。
1.expression 指要產生的元素(參數,變數),放在最前面
2.後面跟上for迴圈
3.for迴圈之後還可以加上if條件判斷,以便進行篩選。
實際使用的過程中,若一個for迴圈不能完成問題,還可以往下嵌套。
1)簡單代碼舉例:
1  egg_list=[]2 for i in range(10):3     egg_list.append("egg%s"%i)4 print(egg_list)5 6 l=["egg%s"%i for i in range(10)]7 print(l)
執行結果:
1 [‘egg0‘, ‘egg1‘, ‘egg2‘, ‘egg3‘, ‘egg4‘, ‘egg5‘, ‘egg6‘, ‘egg7‘, ‘egg8‘, ‘egg9‘]2 [‘egg0‘, ‘egg1‘, ‘egg2‘, ‘egg3‘, ‘egg4‘, ‘egg5‘, ‘egg6‘, ‘egg7‘, ‘egg8‘, ‘egg9‘]
2)稍微有點複雜的,不過也好理解。
 1 #將l 和 s 中每一個元素取出,組成一個新的元組,將所有的結果儲存在列表中 2 l = [1,2,3,4] 3 s = "hello" 4 l1 = [(num,s1) for num in l if num >3 for s1 in s] 5 print(l1) 6  7 l2 = [] 8 for num1 in l : 9     if num1 >3:10         for s2 in s :11             t = (num1 ,s2)12             l2.append(t)13 print(l2)
執行結果:
1 [(4, ‘h‘), (4, ‘e‘), (4, ‘l‘), (4, ‘l‘), (4, ‘o‘)]2 [(4, ‘h‘), (4, ‘e‘), (4, ‘l‘), (4, ‘l‘), (4, ‘o‘)]

通過比較,雖然上邊兩種方式都可以實現功能,但是可以非常明顯的看出:運用傳統意義上的迴圈,去編寫代碼是非常繁瑣複雜的。
而運用 列表產生式,同樣的內容,可以通過一個list快速產生實現功能的代碼,同時寫出的代碼非常簡潔。

3)再舉個例子:讀取檔案的絕對路徑

①代碼:
 1 import os 2 g = os.walk("G:\\zhang")  #拿取檔案路徑下所有的檔案 3 #print(g)  #g是一個產生器 4 l = [] 5 for i in g: #擷取所有檔案的絕對路徑 6     #print(i)  #路徑整體以元組的形式列印出來,元組內部是列表(檔案路徑,檔案名稱,檔案) 7     for j in i[-1]:  #拿取有檔案的路徑 8         file_path = "%s\\%s" % (i[0], j) 9         l.append(file_path)10 print(l)11 12 g = os.walk("G:\\zhang")13 l1 = ["%s\\%s" %(i[0], j) for i in g for j in i[-1]]14 print(l1)
##如果不明白怎麼來的,可以將代碼拷出去,將print釋放,列印的結果即可!檔案路徑可以隨意更改!## 
②執行結果:
1 [‘G:\\zhang\\a3.txt‘, ‘G:\\zhang\\a1\\a1.txt‘, ‘G:\\zhang\\a2\\a2.txt‘]

四、產生器運算式

1、定義:
產生器運算式,我個人認為還不如叫清單產生器,就是把列表運算式改變了一下,變成了一個產生器。
而且這種改變非常簡單,就是把外[]換成了()就建立了一個generator。
通過列表產生式,我們可以直接建立一個列表。但受到記憶體的限制,列表容量肯定是有限的,同時那麼龐大的資料流,一下子拿出來什麼機器得卡的受不了。
而且,建立一個包含100萬個元素的列表,不僅佔用很大的儲存空間,如果我們僅僅需要訪問前面幾個元素,那後面絕大多數元素佔用的空間都白白浪費了。
所以,如果列表元素可以按照某種演算法推算出來,那我們是否可以在迴圈的過程中不斷推算出後續的元素呢?這樣就不必建立完整的list,從而節省大量的空間。
在Python中,這種一邊迴圈一邊計算的機制,稱為產生器:generator。
就昨天所學的產生器的理解來判斷:generator產生器儲存的是演算法,每次通過next()觸發取值,並且每次只取一個元素的值,直到計算到最後一個元素。
沒有更多的元素時,就會拋出StopIteration的錯誤。我們可以通過for迴圈來迭代它,並且不需要關心StopIteration的錯誤。

這種產生器經常運用於:處理檔案,讀取資料庫中大量的資料 的情況之中。
1、簡單代碼舉例:
 1 #還是下蛋的例子(……跟雞過不去了……) 2 l=[‘egg%s‘ %i for i in range(100)] 3 print(l) 4  5 g=l=(‘egg%s‘ %i for i in range(1000000000000000000000000000000000000)) 6 print(g) 7 print(next(g)) 8 print(next(g)) 9 for i in g:10     print(i)
執行結果:
2、處理檔案的代碼舉例:
 1 #處理檔案,去除檔案中每行的空格 2 #傳統處理方式,如果資料很大的話,瞬間將記憶體擠爆…… 3 f=open(‘a.txt‘) 4 l=[] 5  6 for line in f: 7     line=line.strip() 8     l.append(line) 9 print(l)10 11 f=open(‘a.txt‘)12 f.seek(0)13 l1=[line.strip() for line in f]14 print(l1)15 16 f=open(‘a.txt‘)17 f.seek(0)18 g=(line.strip() for line in f)19 print(g)20 print(next(g))21 22 23 #list(可迭代對象)  可以將迭代器轉換成列表24 f=open(‘a.txt‘)25 g=(line.strip() for line in f)26 27 l=list(g)28 print(l)
執行結果:
 View Code
3、應用:聲明式編程
1)求和函數 sum() 可以計算 可迭代的資料的值
1 #1、求和函數 sum() 可以計算 可迭代的資料的值2 print(sum([1,2,3,4])) #直接對列表求和3 nums_g=(i for i in range(3)) #產生器4 print(sum(nums_g))#求和
執行結果:
1 102 3
2)計算購物清單總價
 1 # 計算購物清單總價 2 # 1、傳統方式 3 money_l=[] 4 with open(‘b.txt‘) as f: 5     for line in f: 6         goods=line.split()  #將檔案中的每行以空格分割,然後以列表的形式儲存 7         res=float(goods[-1])*float(goods[-2]) #求和 個數*單價 此處注意資料類型的轉換 str -> float 8         money_l.append(res)  #產生一個總價的列表 9 print(money_l)  #列印列表10 print(sum(money_l))#求總價11 #12 # 2、清單產生器 方法  將上邊的代碼用聲明式編程代替13 f=open(‘b.txt‘)14 g=(float(line.split()[-1])*float(line.split()[-2]) for line in f)15 print(sum(g))16 #
執行結果:
1 [30.0, 1000000.0, 6000.0, 90000.0, 30.0]2 1096060.03 1096060.0
3)資料庫查詢的功能(檔案資料,string)得到的內容是[{},{}]形式,列表套字典的形式。
 1 res=[] 2 with open(‘b.txt‘) as f: 3     for line in f: 4         # print(line) 5         l=line.split() #把每行處理成列表 6         # print(l) 7         d={}  #先定義一個空字典 8         d[‘name‘]=l[0]  #往字典內賦值 9         d[‘price‘]=l[1]  #往字典內賦值10         d[‘count‘]=l[2]  #往字典內賦值11         res.append(d)  #將新建立的字典寫到列表中12 print(res)  #列印結果13 #14 # 產生器運算式 方式 處理15 with open(‘b.txt‘) as f:16     res=(line.split() for line in f)  #得到一個清單產生器 大列表,檔案內所有內容都在17     #print(res) #查看類型 產生器18     dic_g=({‘name‘:i[0],‘price‘:i[1],‘count‘:i[2]} for i in res)  #對迭代器進行取值,拿到每個小列表,組成一個新的字典,存放在新的列表中19     print(dic_g)#查看類型  產生器20     apple_dic=next(dic_g)  #取第一值  前提是知道第一個是什麼21     print(apple_dic[‘count‘])
執行結果:
1 [{‘name‘: ‘apple‘, ‘price‘: ‘10‘, ‘count‘: ‘3‘}, {‘name‘: ‘tesla‘, ‘price‘: ‘1000000‘, ‘count‘: ‘1‘}, {‘name‘: ‘mac‘, ‘price‘: ‘3000‘, ‘count‘: ‘2‘}, {‘name‘: ‘lenovo‘, ‘price‘: ‘30000‘, ‘count‘: ‘3‘}, {‘name‘: ‘chicken‘, ‘price‘: ‘10‘, ‘count‘: ‘3‘}]2 <generator object <genexpr> at 0x00000000028EB360>3 3

此處有一個非常有趣的問題,昨天所學,我們知道檔案本身就是一個迭代器。

next()取值之後,會將檔案關閉。往後就無法再取值,所以會有I/O錯誤 沒法讀取 檔案關閉的報錯。
所以調用檔案的話,建議用 f = open("b.txt") 或是next()觸發取值的話,縮近放在裡邊。

4)取出單價>10000 大體不變,只是將每行組成的列表,格式化 轉換成字典的時候進行過濾,取出滿足條件的內容
1 # 取出單價>10000  大體不變,只是將每行組成的列表,格式化 轉換成字典的時候進行過濾,取出滿足條件的內容2 with open(‘b.txt‘) as f:3     res=(line.split() for line in f)4     # print(res)5     dic_g=({‘name‘:i[0],‘price‘:i[1],‘count‘:i[2]} for i in res if float(i[1]) > 10000)6     print(dic_g)7     #print(list(dic_g))  #直接取值8     for  i in dic_g:  #for迴圈取值9         print(i)

執行結果:

1 <generator object <genexpr> at 0x00000000026BB3B8>2 {‘name‘: ‘tesla‘, ‘price‘: ‘1000000‘, ‘count‘: ‘1‘}3 {‘name‘: ‘lenovo‘, ‘price‘: ‘30000‘, ‘count‘: ‘3‘}

 

 

python協程函數應用 列表產生式 產生器運算式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.