標籤:alt adl lin ase 有一個 enc 多個 utf-8 inpu
昨天學了很多函數方面的概念和知識其中有一個閉包的函數。很多人都對閉包的作用不是很清楚,今天我們就來認識一個新的知識點裝飾器。它就是閉包函數的一個經典應用。
預習:
編寫裝飾器,為多個函數加上認證的功能(使用者的帳號密碼來源於檔案),要求登入成功一次,後續的函數都無需再輸入使用者名稱和密碼
一、楔子
def func1(): print(‘in func1‘)
想要計算上面函數的執行時間:
import timedef func1(): start = time.time() print(‘in func1‘) end =print(time.time() - end)
func1()
可是如果你要計算你寫過的所有函數的執行時間就要挨個去改代碼。寫個函數可不可以:
import timedef timer(func): start = time.time() func() print(time.time() - start)def func1(): print(‘in func1‘)def func2(): print(‘in func2‘)timer(func1)timer(func2)
不管我們寫了多少個函數都可以調用這個計時函數來計算函數的執行時間了。。。儘管現在修改成本已經變得很小很小了,但是還是改變了這個函數的調用方式,如果有很多函數還是要改很多
你要做的就是,讓你的同事依然調用func1,但是能實現調用timer方法的效果
import timedef timer(func): start = time.time() func() print(time.time() - start)def func1(): print(‘in func1‘)func1 =timer(func1) #報錯func1()
非常可惜,上面這段代碼是會報錯的,因為timer方法需要傳遞一個func參數,我們不能在賦值的時候傳參,因為只要執行func1 = timer(func1),timer方法就直接執行了,下面的那句func1根本就沒有意義。
二、裝飾器的形成
器即函數
裝飾即修飾,意指為其他函數添加新功能
裝飾器定義:本質就是函數,功能是為其他函數添加新功能
import timedef func1(): print(‘in func1‘)def timer(func): def inner(): start = time.time() func() print(time.time() - start) return innerfunc1 = timer(func1)func1()
裝飾器——簡單版1
現在唯一麻煩就是還要在做一次賦值調用。。。python的開發人員也覺得礙眼,所以就為我們提供了一句文法糖來解決這個問題!
import timedef timer(func): def inner(): start = time.time() func() print(time.time() - start) return inner@timer #==> func1 = timer(func1)def func1(): print(‘in func1‘)func1()
裝飾器——文法糖
到這裡,我們可以簡單的總結一下:
裝飾器的本質:一個閉包函數
裝飾器的功能:在不修改原函數及其調用方式的情況下對原函數功能進行擴充
最後一個問題要解決,剛剛我們討論的裝飾器都是裝飾不帶參數的函數,現在要裝飾一個帶參數的函數怎麼辦
def timer(func): def inner(a): start = time.time() func(a) print(time.time() - start) return inner@timerdef func1(a): print(a)func1(1)
裝飾器——帶參數的裝飾器
假如你有兩個函數,需要傳遞的參數不一樣
import timedef timer(func): def inner(*args,**kwargs): start = time.time() re = func(*args,**kwargs) print(time.time() - start) return re return inner@timer #==> func1 = timer(func1)def func1(a,b): print(‘in func1‘)@timer #==> func2 = timer(func2)def func2(a): print(‘in func2 and get a:%s‘%(a)) return ‘fun2 over‘func1(‘aaaaaa‘,‘bbbbbb‘)print(func2(‘aaaaaa‘))
裝飾器—萬能裝飾器
如果你的函數是有傳回值的
import timedef timer(func): def inner(*args,**kwargs): start = time.time() re = func(*args,**kwargs) print(time.time() - start) return re return inner@timer #==> func2 = timer(func2)def func2(a): print(‘in func2 and get a:%s‘%(a)) return ‘fun2 over‘func2(‘aaaaaa‘,‘bbbbbb‘)print(func2(‘aaaaaa‘))
裝飾器—帶傳回值的裝飾器
三、開放封閉原則
1、對擴充是開放的
我們說,任何一個程式,不可能在設計之初就已經想好了所有的功能並且未來不做任何更新和修改。所以我們必須允許代碼擴充、添加新功能。
2、對修改是封閉的
就像我們剛剛提到的,因為我們寫的一個函數,很有可能已經交付給其他人使用了,如果這個時候我們對其進行了修改,很有可能影響其他已經在使用該函數的使用者。
裝飾器完美的遵循了這個開放封閉原則。
四、裝飾器的主要功能和裝飾器的固定結構
裝飾器的主要功能:
在不改變函數調用方式的基礎上在函數的前、後添加功能。
裝飾器的固定格式:
def timer(func): def inner(*args,**kwargs): ‘‘‘執行函數之前要做的‘‘‘ re = func(*args,**kwargs) ‘‘‘執行函數之後要做的‘‘‘ return re return inner
裝飾器的固定格式
五、帶參數的裝飾器
未完待續
預習解答:
#編寫裝飾器,為多個函數加上認證的功能(使用者的帳號密碼來源於檔案),要求登入成功一次,#後續的函數都無需再輸入使用者名稱和密碼# tag = Truetag = [True]def rz(func) : def inner() : # global tag # while tag : while tag[0] : name = input("please input your name:").strip() passworld = input("please input your passworld:").strip() with open("demo.py", ‘r‘, encoding=‘utf-8‘) as read_f : print() if read_f.readline() == name+"\n" and read_f.readline() == passworld+"\n" : # tag = False tag[0] = False func() return inner@rzdef func() : print("lln")@rzdef func1() : print("lln1")@rzdef func2() : print("lln2")func()func1()func2()預習答案
python函數(3):裝飾器