Day4 - Python基礎4 叠代器、裝飾器、軟件開發規範
Day4 - Python基礎4 叠代器、裝飾器、軟件開發規範
1.叠代器&生成器
生成器
背景:通過列表生成式能生成一個列表,但受內存限制,列表的容量肯定是有限的。而且當列表元素很多時,會占用大量內存空間,如果只是使用其中的一些元素,那其它元素會造成空間浪費
定義:基於以上原因,如果能通過算法推導出列表的元素,這樣就不需要創建完整的list,可以節省空間。這種一邊循環一邊計算的機制,就叫生成器。
格式:只需把列表生成式[]改成()即可
方法:使用next()可以獲取下一個元素,不過一般用for循環打印
函數生成器:在函數中加入yield,函數就變成了一個生成器;而且還可以利用此特性,實現協程的效果
1 #普通列表 2 list_normal = [0,1,2,3,4,5,6,7,8,9,10] #手動生成列表 3 print(list_normal) 4 #列表生成式 5 list_auto = [i for i in range(11)] #利用算法生成列表 6 print(list_auto) 7 8 #生成器 9 list_generator = (i for i in range(11)) #把生成式[]改成()就是生成器了 10 print(list_generator) 11 #生成器方法 12 print(next(list_generator))13 print(next(list_generator)) 14 for i in list_generator: 15 print(i)
1 #函數生成器 2 def num_generator(num): 3 i = 0 4 while i <num: 5 #print(i) 6 yield i 7 i +=1 8 return ‘done‘ 9 10 nums = num_generator(5) 11 print(nums) 12 print(nums.__next__())函數生成器13 print(nums.__next__()) 14 print("幹點其它事") 15 print(nums.__next__()) 16 print(nums.__next__()) 17 print(nums.__next__()) 18 #函數生成器異常捕獲處理 19 while True: 20 try: 21 print("nums:",next(nums)) 22 except StopIteration as e: 23 print("nums gererator return value:",e.value) 24 break
1 #單線程實現並發運算 2 import time,os 3 4 def command(): 5 print("開始ping啦") 6 while True: 7 addr = yield 8 os.system("ping "+‘ ‘+ addr) 9 10 def ips(): 11 t = command() 12 t.__next__() 13 print("開始分配IP地址") 14 for i in range(2): 15 if i == 0: 16 continue 17 else: 18 address = "10.172.116.%s"%i 19 time.sleep(1) 20 t.send(address) 21 ips()單線程實現並發運算
叠代器
可叠代對象Iterable:
可以被for循環的數據類型,包含二類:
1.集合數據類型:list、dict、tuple、set、str等
2.generator,包含生成器、帶yield的generator function
1 from collections import Iterable 2 from collections import Iterator 3 4 #判斷是否是可叠代對象 5 isinstance([],Iterable) 6 isinstance({},Iterable) 7 isinstance((),Iterable) 8 isinstance(‘string‘,Iterable) 9 isinstance(100,Iterable) #數字不可叠代
叠代器Iterator:
定義:可以被next()函數調用並不斷返回下一個值的對象稱為叠代器
特性:
把Iterable變成Iterator可以使用Iter()函數
生成器都是Iterator對象,但list、tuple、dict等雖是Iterable,卻不是Iterator
1 #判斷是否是叠代器 2 isinstance([],Iterator) 3 isinstance({},Iterator) 4 isinstance((),Iterator) 5 isinstance(‘string‘,Iterator) 6 isinstance(100,Iterator) 7 isinstance((x for x in range(10)),Iterator) 8 9 #叠代對象轉換成叠代器方法 10 Iter_list = iter([1,2,3]) 11 print(iter_list)
區別:
Iterator對象表示的是一個數據流,可以被next()函數調用並不斷返回下一個數據,直到數據拋出StopIteration錯誤。可以把Iterator看成是一個有序序列,但我們卻不能提前知道序列長度,它可以表示一個無限大的數據流,如自然數,而這是list辦不到的。
for循環本質上是通過不斷調用next()實現的
1 #for循環 2 for i in [1,2,3]: 3 print(i) 4 5 #等同於下面的叠代器 6 a = iter([1,2,3]) 7 while True: 8 try: 9 next(a) 10 except StopIteration: 11 breakView Code
2.裝飾器
python裝飾器:http://blog.51cto.com/egon09/1836763
定義:本質是函數,功能是裝飾其它函數,就是為其它函數添加附加功能
原則:1.不能修改被裝飾的函數的源代碼(對被裝飾函數是透明的)
2.不能修改被裝飾的函數的調用方式
實現裝飾器知識儲備:(高階函數+嵌套函數=裝飾器)
1.函數即“變量”
2.高階函數
a.把一個函數名當做實參傳給另一個函數(在不修改被裝飾函數源代碼的情況下為其添加功能)
b.返回值中包含函數名(不修改函數的調用方式)
1 #高階函數 2 def bar(): 3 time.sleep(3) 4 print(‘in the bar‘) 5 6 def test2(func): 7 print(func) 8 return func 9 10 t = test2(bar) 11 t() #run bar 12 13 bar=test2(bar) #把之前函數bar名稱覆蓋了 14 bar()高階函數
3.嵌套函數
定義:一個函數體內用def去聲明一個新的函數
1 #嵌套函數 2 def foo(): 3 print(‘in the foo‘) 4 def bar(): 5 print(‘in the bar‘) 6 bar() 7 foo()嵌套函數
1 #局部作用域和全局作用域的訪問順序 2 x=0 3 def grandpa(): 4 x=1 5 def dad(): 6 x=2 7 def son(): 8 x=3 9 print(x) 10 son() 11 dad() 12 grandpa() #結果是3,從最裏面找變量局部作用域和全局作用域的訪問順序
4.裝飾器案例
1 #裝飾器案例1 2 #運行test1-->等同於運行deco-->運行deco過程中會運行原來的test1函數-->並附加了計時功能 3 def timer(func): #嵌套函數 timer(test1) func=test1 4 def deco(): #高階函數 5 start_time = time.time() 6 func() #run test1 7 stop_time = time.time() 8 print("run time :%s"%(stop_time-start_time)) 9 return deco #返回deco的內存地址 10 11 @timer #等同於test1 = timer(test1) 12 def test1(): 13 time.sleep(3) 14 print(‘in the test1‘) 15 16 test1() #run deco裝飾器案例1
1 1 #裝飾器案例2 2 2 #實現不定量傳參,裝飾器更有擴展性 3 3 def timer(func): #嵌套函數 timer(test1) func=test1 4 4 def deco(*arg,**kwargs): #高階函數 5 5 start_time = time.time() 6 6 func(*arg,**kwargs) #run test1 7 7 stop_time = time.time() 8 8 print("run time :%s"%(stop_time-start_time)) 9 9 return deco #返回deco的內存地址 10 10 11 11 @timer #等同於test1 = timer(test1) 12 12 def test1(): 13 13 time.sleep(3) 14 14 print(‘in the test1‘) 15 15 16 16 @timer #等同於test2 = timer(test2)=deco test2(name)=deco(name) 17 17 def test2(name): 18 18 print(‘test2:‘,name) 19 19 20 20 test1() #run deco 21 21 test2(‘sam‘)裝飾器案例2-傳參
1 #網站認證裝飾器-初版 2 #需求:登錄index頁面不需要認證,登錄home/bbs要認證(使用裝飾器) 3 user,passwd = ‘sam‘,‘123‘ 4 def auth(func): #裝飾器 5 def wrapper(): 6 username = input("Username:").strip() 7 password = input("Password:").strip() 8 if username == user and password == passwd: 9 print("登錄成功!") 10 func() 11 else: 12 print("用戶名或密碼錯誤.") 13 return wrapper 14 15 def index(): #不認證 16 print("Welcome to the index page.") 17 18 @auth 19 def home(): #裝飾器認證 20 print("Welcome to the home page.") 21 22 @auth 23 def bbs(): #裝飾器認證 24 print("Welcome to the bbs page.") 25 26 home() 27 bbs()網站認證裝飾器-初版
1 #網站認證裝飾器-進階版 2 #需求:登錄index頁面不需要認證,登錄home/bbs要使用認證方式(使用裝飾器),home傳參數且有返回值 3 user,passwd = ‘sam‘,‘123‘ 4 def auth(func): 5 def wrapper(*args,**kwargs): 6 username = input("Username:").strip() 7 password = input("Password:").strip() 8 if username == user and password == passwd: 9 print("登錄成功!") 10 res = func(*args,**kwargs) 11 #print("---認證之後---") 12 return res 13 else: 14 print("用戶名或密碼錯誤.") 15 return wrapper 16 17 def index(): 18 print("Welcome to the index page.") 19 20 @auth 21 def home(*args): 22 print("Welcome to the home page.",args) 23 return "From home page" 24 25 @auth 26 def bbs(): 27 print("Welcome to the bbs page.") 28 29 #home() 30 print(home(‘sam‘))網站認證裝飾器-進階版
1 #網站認證裝飾器-終極版 2 #需求:登錄index頁面不需要認證,登錄home/bbs要使用不同的認證方式local/ldap(使用裝飾器),home傳參數且有返回值 3 user,passwd = ‘sam‘,‘123‘ 4 def auth(auth_type): 5 #print("auth func:",auth_type) 6 def outer_wrapper(func): 7 def wrapper(*args,**kwargs): 8 #print("wrapper func args:", *args, **kwargs) 9 if auth_type == ‘local‘: 10 username = input("Username:").strip() 11 password = input("Password:").strip() 12 if username == user and password == passwd: 13 print("登錄成功!") 14 res = func(*args,**kwargs) 15 #print("---認證之後---") 16 return res 17 else: 18 print("用戶名或密碼錯誤.") 19 elif auth_type == ‘ldap‘: 20 print("使用Ldap認證") 21 return wrapper 22 return outer_wrapper 23 24 def index(): 25 print("Welcome to the index page.") 26 27 @auth(auth_type=‘local‘) #home=auth 28 def home(*args): 29 print("Welcome to the home page.",args) 30 return "From home page" 31 32 @auth(auth_type=‘ldap‘) 33 def bbs(): 34 print("Welcome to the bbs page.") 35 36 home() 37 bbs()網站認證裝飾器-終極版
3.Json & pickle 數據序列化
xml逐漸被json取代
Json不支持函數序列化,只能處理簡單的數據類型
#序列化 import json def sayhi(name): print("hello,",name) info = { ‘name‘:‘alex‘, ‘age‘:22, #‘func‘:sayhi #不能序列化函數 } f = open("test.text","w") f.write( json.dumps( info) ) info[‘age‘] = 21 f.write( json.dumps( info) ) f.close() #反序列化 import json f = open("test.text","r") #data = json.loads(f.read()) #data = pickle.loads(f.read()) for line in f: print(json.loads(line))Json
Json是不同開發語言都支持的交互方式,pickle是python自有的
pickle可以序列化所有數據類型,但函數不能序列
1 #序列化 2 import pickle 3 4 def sayhi(name): 5 print("hello,",name) 6 7 info = { 8 ‘name‘:‘alex‘, 9 ‘age‘:22, 10 ‘func‘:sayhi 11 } 12 13 14 f = open("test.text","wb") 15 16 pickle.dump(info,f) #和f.write( pickle.dumps( info) )功能一樣 17 18 f.close() 19 20 #反序列化 21 def sayhi(name): 22 print("hello2,",name) 23 24 f = open("test.text","rb") 25 26 data = pickle.load(f) #和data = pickle.loads(f.read())功能一樣 27 28 print(data["func"]("Alex"))View Code
註:dump一次load一次,不要dump多次
4.軟件目錄結構規範
bin-執行文件
site-packages--模組
main-主程序
docs-說明文檔
Day4 - Python基礎4 叠代器、裝飾器、軟件開發規範