1. 程式人生 > >Day4 - Python基礎4 叠代器、裝飾器、軟件開發規範

Day4 - Python基礎4 叠代器、裝飾器、軟件開發規範

The 用戶 主程 容量 自然數 num tin class 本質

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         break
View 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 叠代器、裝飾器、軟件開發規範