Python開發之路——7
一、叠代器
1.叠代器協議
(1)叠代器協議是指:對象必須提供一個next方法,執行該方法要麽返回叠代中的下一項,要麽引起一個StopIteration移除異常以中止叠代。
(2)可叠代對象:實現了叠代器協議的對象(實現方法:在對象內部定義一個__iter__()方法)
(3)協議是一種約定,可叠代對象實現了叠代器協議,Python的內部工具如:for循環,sum,min,max等使用叠代器協議訪問對象
2.for循環
(1)for 循環的本質:使用叠代器協議循環所有對象
(2)字符串、列表、元組、字典、集合、文件對象都不是可叠代對象,在for循環時,調用了內部的__iter__()方法,把它們變成了可叠代對象
(3)for循環調用可叠代對象的__next__()方法,並捕捉StopIteration異常來中止叠代
![技術分享圖片](/img/jia.gif)
l = [1,2,3] iter_l = l.__iter__() print(iter_l.__next__()) print(iter_l.__next__()) print(next(iter_l))#python內置的next print(iter_l.__next__())View Code
(4)for循環就是基於可叠代協議提供了一個統一的可以叠代所有對象的方法,即在遍歷之前,先調用對象內部的__iter__()方法,將對象轉化成叠代器,然後利用叠代器協議去循環訪問。
![技術分享圖片](/img/jia.gif)
# while模擬for循環 l = [1,2,3,4,5] diedai_l=l.__iter__() while True: try: print(diedai_l.__next__()) except StopIteration: print("叠代結束") breakView Code
二、生成器
1.三元表達式
![技術分享圖片](/img/jia.gif)
name = "Kobe" res = "Lakers" if name=="Kobe" else "Other Team" print(res)View Code
2.列表解析
![技術分享圖片](/img/jia.gif)
l = [x*x forView Codex in range(20) if x%2==0] print(l) l=[] for x in range(20): if x%2==0: l.append(x*x) print(l)
3.生成器
(1)生成器是一種自動實現可叠代協議的數據類型,不需要調用__iter__方法,所以生成器就是一種可叠代對象
(2)生成器在Python中有兩種產生形式
a.生成器函數:與常規函數類似,但返回值不用return而是用yield。yield每次返回一個結果,返回後函數狀態掛起,下次執行從掛起的狀態繼續執行
b.生成器表達式:與列表解析類似,把列表解析式的[]改為()就創建了一個生成器,生成器是按照需要每次產生一個結果,而不是直接構建完整的結果
(3)生成器的優點:a.可以延遲操作,即在需要的時候產生結果,可以節省內存;b.可以提高代碼可讀性
人口普查
![技術分享圖片](/img/jia.gif)
def population_get(): with open("人口普查.txt","r",encoding="utf-8") as f: for i in f: yield i g = population_get() all_pop = sum(int(eval(i)["population"]) for i in g ) print(all_pop) for p in g: print("%s %%"%int(eval(i)["population"])/all_pop)#因為生產器已經叠代了一遍,所以不會有輸出結果View Code
生產者消費者模型
![技術分享圖片](/img/jia.gif)
def produce_baozi(): ret = [] for i in range(100): ret.append("包子%s"%i) return ret def consumer(res): for index,baozi in enumerate(res): print("第%s人吃掉了第%s個包子"%(index,baozi)) a = produce_baozi() consumer(a)View Code
三、裝飾器
1.裝飾器:
本質就是函數,為其他函數添加附加功能,裝飾器功能的實現需要用到高階函數+函數嵌套+閉包
2.原則:
(1)不改變被修飾函數的源代碼
(2)不改變被修飾函數的調用方式
3.高階函數
滿足下面任意一條的函數即是高階函數
(1)函數接收的參數是一個函數名
(2)函數的返回值是一個函數名
高階函數在裝飾器中的作用:
(1)函數的接收值是一個函數名
可以在不修改源代碼的前提下,為函數添加新功能,但是會改變函數的調用方式
(2)函數的返回值是一個函數名
不會改變函數的調用方式,但是不能為函數添加新功能
![技術分享圖片](/img/jia.gif)
import time def foo(): time.sleep(3) print("hello,賀醜子") def timer(func): start_time=time.time() func() end_time=time.time() print("程序運行時間 %s" %(end_time-start_time)) return func foo = timer(foo) foo()View Code
4.最後實現
![技術分享圖片](/img/jia.gif)
import time def timmer(func): def wrapper(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print("程序運行時間%s" %(stop_time-start_time)) return res return wrapper @timmer def test1(name,age): time.sleep(3) print("hello,world,,名字是%s,年齡是%s"%(name,age)) return "這是test1的返回值" res=test1("hehcouzi",17) print(res)View Code
四、一個文件操作系統
![技術分享圖片](/img/jia.gif)
# 實現功能:1.函數操作 2.文件處理 3.tag的用法 4.文件的解耦 import os def file_handler(backend_data,res=None,type="fetch"):#文件的解耦 if type == "fetch": with open("haproxy.conf","r") as read_f: tag = False#tag用法 ret= [] for read_line in read_f: if read_line.strip()==backend_data: tag =True continue if tag and read_line.startswith("backend"): break if tag: print(read_line,end="") ret.append(read_line) return ret elif type == "change": with open("haproxy.conf", "r") as read_f, open("haproxy.conf_new", "w") as write_f: tag = False has_write = False for read_line in read_f: if read_line.strip() == backend_data: tag = True continue if tag and read_line.startswith("backend"): tag = False if not tag: write_f.write(read_line) else: if not has_write: for record in res: write_f.write(record) has_write = True os.rename("haproxy.conf", "haproxy.conf.bak") os.rename("haproxy.conf_new", "haproxy.conf") os.remove("haproxy.conf.bak") def fetch(data): print("這是查詢功能") print("用戶數據是",data) backend_dat= "backend %s" %data return (file_handler(backend_dat)) def add(): pass def change(data): backend=data[0]["backend"] backend_data="backend %s" %backend old_server_record="%sserver %s %s weight %s maxconn %s\n" %(" "*8,data[0]["record"]["server"], data[0]["record"]["server"], data[0]["record"]["weight"], data[0]["record"]["maxconn"]) new_server_record="%sserver %s %s weight %s maxconn %s\n" %(" "*8,data[1]["record"]["server"], data[1]["record"]["server"], data[1]["record"]["weight"], data[1]["record"]["maxconn"]) print("用戶想要修改的記錄是:",old_server_record) res = fetch(backend) print("來自change函數讀取的內容:",res) if not res or old_server_record not in res: print("沒有找到要修改的內容") else: index = res.index(old_server_record) res[index]=new_server_record res.insert(0,"%s\n" %backend_data) file_handler(backend_data,res=res,type="change") return res def delete(): pass if __name__ == "__main__":#判斷功能 msg=‘‘‘ 1:查詢 2:增加 3:修改 4:刪除 5:退出 ‘‘‘ msg_dic={ "1":fetch, "2":add, "3":change, "4":delete, } while True: print(msg) choice = input("請輸入你的選項: ").strip() if not choice:continue if choice == "5": break data = input("請輸入你的數據:").strip() if choice != "1": data = eval(data) res = msg_dic[choice](data) print(res) # [{"backend":"www.oldboy1.org","record":{"server":"2.2.2.4","weight":"20","maxconn":"3000"}},{"backend":"www.oldboy1.org","record":{"server":"2.2.2.5","weight":"20","maxconn":"3000"}}]View Code
一些小的補充:
![技術分享圖片](/img/jia.gif)
#一一對應 a,b,c = (1,2,3) print(a,b,c) #只取頭尾 l = [11,22,33,44,55,66,77] a,*_,c = l print(a,c) #交換位置 f1 = 1 f2 = 2 f1,f2 = f2,f1 print(f1,f2)View Code
Python開發之路——7