標籤:return 傳回值 inpu pre sse username wrap 全域 固定
裝飾器
定義:本職是函數,(裝飾其他函數)就是為其他函數添加附加功能。
原則:
1.不能修改被裝飾的函數的原始碼
2.不能修改被裝飾函數的調用的方式
先來一個直觀感受import timedef timmer(func): ## def warpper(*args,**kwargs): start_time=time.time() func() ##run test1() stop_time=time.time() print("the func time is %s"%(start_time-stop_time)) return warpper@timmer #@加函數名,即可調用函數def test1(): ###原始碼 time.sleep(3) print("in the test1")test1()
實現裝飾器的知識儲備:
1.函數即"變數"
2.高階函數
3.嵌套函數(函數裡面def聲明一個函數叫嵌套函數,調用函數不叫嵌套)
下面進行一波實驗:如下三種結果(驗證1.函數即“變數”)A.輸出報錯沒有bar函數def foo(): print("in the foo") bar()foo()B.成功def bar(): print("in the bar")def foo(): print("in the foo") bar()foo()C.輸出報錯,沒找到定義的bar函數def foo(): print("in the foo") bar()foo()def bar(): print("in the bar")
在將函數即“變數”的時候,先講下python記憶體儲存變數的機制。
當設定一個變數x=1時,記憶體看成一個大house,這時候大house會騰出一個房間將變數值1放入這個房間,並貼上x的門牌號。
如果是x=1,y=x,那就是變數值1這個房間將會有兩個門牌號,即x&y。:
而在python記憶體的回收機制中,當你的房間沒有門牌號時,它就會預設回收。這樣可以節約空間。而當兩個或多個變數值都一樣時,它不會給你建立N個房間,而是同一個房間內貼上N個門牌號。
凡是也有例外,有人就會說了,那就不會有沒有變數名的變數了嗎?這個在python中,還真有即匿名函數lambda。當lambda x:x*3,結果是佔用的記憶體位址。
這裡的
print(“in the poo”)
bar()
就是函數體相當於變數存放在記憶體中。poo()就是門牌號,當執行A時之所以會報錯,就是因為沒有找到bar的函數體。而C雖然定義了bar()但是定義的位置不對,函數都是從上往下讀取,當執行poo()之前並沒有定義,所以會報錯找不到bar
2.高階函數(又分以下兩種)
a:把一個函數名當做實參傳遞給另外一個函數import timedef bar(): time.sleep(3) print("in the bar")def test1(func): ##根據test1(bar)的調用可以看出,這裡的func = bar。這就是把bar函數名傳遞給func當test1的實參 start_time=time.time() func() #run bar() stop_time=time.time() print("the func run time is %s"%(stop_time-start_time))test1(bar)b:傳回值中包含函數名import timedef bar(): time.sleep(3) print("in the bar")def test2(func): print(func) return func #f返回bar的記憶體值print(test2(bar))t=test2(bar) #test2執行結果賦值給了t,相當於把bar(賦值給了t,當使用t()時,就是在執行bar函數t() #run bar()
3.嵌套函數 (在一個函數體內用def聲明一個函數叫嵌套。調用不叫嵌套)
#局部即變數def foo(): def bar(): print("in the bar") bar() ##想要輸出print結果就需要一層層的調用foo()#局部作用和全域範圍的訪問順序x=0def boo(): def daa(): x=2 def son(): x=3 print(x) son() daa()boo()猜測下這裡的輸出結果是:
下面寫個簡單的裝飾器。(高階函數+嵌套函數=》裝飾器)
不設定函數實參
import timedef timer(func): ##func=test1=test2 def deco(): start_time=time.time() func() ##func=test1 =test2 stop_time=time.time() print("the funce run time is %s" %(stop_time-start_time)) return decodef test1(): time.sleep(3) print("in the test1")@timerdef test2(): time.sleep(3) print("in the test2")test1=timer(test1)test1() ##-->decotest2()
當設定test實參時,可以這樣寫。deco() func()裡面都直接*args,***kwargs不限量。如果具體某一個參數,那就可以修改為具體的。
import timedef timer(func): def deco(*args,**kwargs): start_time=time.time() func(*args,**kwargs) stop_time=time.time() print("the funce run time is %s" %(stop_time-start_time)) return decodef test1(): time.sleep(3) print("in the test1")@timer #非固定參數namedef test2(name): time.sleep(3) print("in the test2",name)test1=timer(test1)test1() ##-->decotest2("alex")
類比遠端登入與本地登入實驗:
user,passwd="alex","abc"def auth(auth_type): print("auth>>>",auth_type) def outer_wrapper(func): def wrapper(*args,**kwargs): print("*args,**kwargs",*args,**kwargs) if auth_type=="local": username=input("Input user: ").strip() password=input("Input password: ").strip() if username==user and password==passwd: print("\033[32;1mUser has passed authentication\033[0m") res=func(*args,**kwargs) return res else: exit("\033[31;1mIminvalid username or password\033[0m") elif auth_type=="ldap": print("不會") return wrapper return outer_wrapperdef index(): print("welcome to index page")@auth(auth_type="local") ##本地驗證登入def home(): print("welcome to home page") return "from home"@auth(auth_type="ldap") ##遠端驗證登入def dds(): print("welcome to dds page")index()print(home())dds()
【24】Python裝飾器筆記