您好,登錄后才能下訂單哦!
本文實(shí)例講述了Python3.5裝飾器原理及應(yīng)用。分享給大家供大家參考,具體如下:
1、裝飾器:
(1)本質(zhì):裝飾器的本質(zhì)是函數(shù),其基本語(yǔ)法都是用關(guān)鍵字def去定義的。
(2)功能:裝飾其他函數(shù),即:為其他函數(shù)添加附加功能。
(3)原則:不能修改被裝飾的函數(shù)的源代碼,不能修改被裝飾的函數(shù)的調(diào)用方式。即:裝飾器對(duì)待被修飾的函數(shù)是完全透明的。
(4)簡(jiǎn)單應(yīng)用:統(tǒng)計(jì)函數(shù)運(yùn)行時(shí)間的裝飾器
import time #統(tǒng)計(jì)函數(shù)運(yùn)行時(shí)間的磚裝飾器 def timmer(func): def warpper(*args,**kwargs): strat_time = time.time() func() stop_time = time.time() print("the func run time is %s" %(stop_time-strat_time)) return warpper @timmer def test1(): time.sleep(3) print("in the test1") test1()
運(yùn)行結(jié)果:
in the test1
the func run time is 3.000171661376953
(5)實(shí)現(xiàn)裝飾器知識(shí)儲(chǔ)備:
a、函數(shù)即“變量”
b、高階函數(shù)
c、函數(shù)嵌套
d、高階函數(shù)+嵌套函數(shù)==》裝飾器
2、裝飾器知識(shí)儲(chǔ)備——函數(shù)即“變量”
定義一個(gè)函數(shù),相當(dāng)于把函數(shù)體賦值給這個(gè)函數(shù)名。
Python解釋器如何回收變量:采用引用計(jì)數(shù)。當(dāng)引用有沒有了時(shí)(門牌號(hào)不存在),變量就被回收了。
函數(shù)的定義也有內(nèi)存回收機(jī)制,與變量回收機(jī)制一樣。匿名函數(shù)沒有函數(shù)名,就會(huì)被回收。
變量的使用:先定義再調(diào)用,只要在調(diào)用之前已經(jīng)存在(定義)即可;函數(shù)即“變量”,函數(shù)的使用是一樣的。
函數(shù)調(diào)用順序:其他的高級(jí)語(yǔ)言類似,Python 不允許在函數(shù)未聲明之前,對(duì)其進(jìn)行引用或者調(diào)用
下面的兩段代碼運(yùn)行效果一樣:
def bar(): print("in the bar") def foo(): print("in the foo") bar() foo() #python為解釋執(zhí)行,函數(shù)foo在調(diào)用前已經(jīng)聲明了bar和foo,所以bar和foo無順序之分 def foo(): print("in the foo") bar() def bar(): print("in the bar") foo()
運(yùn)行結(jié)果:
in the foo
in the bar
in the foo
in the bar
注意:python為解釋執(zhí)行,函數(shù)foo在調(diào)用前已經(jīng)聲明了bar和foo,所以bar和foo無順序之分
原理圖為:
3、裝飾器知識(shí)儲(chǔ)備——高階函數(shù)
滿足下列其中一種即可稱之為高階函數(shù):
a、把一個(gè)函數(shù)名當(dāng)做實(shí)參傳遞給另一個(gè)函數(shù)(在不修改被裝飾函數(shù)的情況下為其添加附加功能)
b、返回值中包含函數(shù)名(不修改函數(shù)的調(diào)用方式)
(1)高階函數(shù)示例:
def bar(): print("in the bar") def test1(func): print(func) #打印門牌號(hào),即內(nèi)存地址 func() test1(bar) #門牌號(hào)func=bar
運(yùn)行結(jié)果:
<function bar at 0x00BCDFA8>
in the bar
(2)高階函數(shù)的妙處——把一個(gè)函數(shù)名當(dāng)做實(shí)參傳遞給另一個(gè)函數(shù)(在不修改被裝飾函數(shù)的情況下為其添加附加功能)
import time def bar(): time.sleep(3) print("in the bar") #test2在不修改被修飾函數(shù)bar的代碼時(shí)添加了附加的及時(shí)功能 def test2(func): start_time = time.time() func() #run bar stop_time = time.time() print("the func run time is %s " %(stop_time-start_time)) #調(diào)用方式發(fā)生改變,不能像原來的方法去調(diào)用被修飾的函數(shù)(所以不能實(shí)現(xiàn)裝飾器的功能) test2(bar) #bar()
運(yùn)行結(jié)果:
in the bar
the func run time is 3.000171661376953
(3)高階函數(shù)的妙處——返回值中包含函數(shù)名(不修改函數(shù)的調(diào)用方式)
import time def bar(): time.sleep(3) print("in the bar") def test3(func): print(func) return func bar = test3(bar) bar() #run bar
運(yùn)行結(jié)果:
<function bar at 0x00BADFA8>
in the bar
4、裝飾器知識(shí)儲(chǔ)備——嵌套函數(shù)
#函數(shù)嵌套 def foo(): print("in the foo") def bar(): #bar函數(shù)具有局部變量的特性,不能在外部調(diào)用,只能在內(nèi)部調(diào)用 print("in the bar") bar() foo()
運(yùn)行結(jié)果:
in the foo
in the bar
裝飾器應(yīng)用——模擬網(wǎng)站登錄頁(yè)面,訪問需要認(rèn)證登錄頁(yè)面
#!/usr/bin/env python # -*- coding:utf-8 -*- # Author:ZhengzhengLiu #模擬網(wǎng)站,訪問頁(yè)面和部分需要登錄的頁(yè)面 import timer user,passwd = "liu","liu123" def auth(func): def wrapper(*args,**kwargs): username = input("Username:").strip() password = input("Password:").strip() if username == user and password == passwd: print("\033[32;1mUser has passed authentication!\033[0m") res = func(*args,**kwargs) print("-----after authentication---") return res else: exit("\033[31;1mInvalid username or password!\033[0m") return wrapper def index(): print("welcome to index page!") @auth def home(): print("welcome to index home!") return "from home" @auth def bbs(): print("welcome to index bbs!") #函數(shù)調(diào)用 index() print(home()) bbs()
運(yùn)行結(jié)果:
welcome to index page!
Username:liu
Password:liu123
User has passed authentication!
welcome to home page!
-----after authentication---
from home
Username:liu
Password:liu123
User has passed authentication!
welcome to bbs page!
-----after authentication---
裝飾器帶參數(shù)
#!/usr/bin/env python # -*- coding:utf-8 -*- # Author:ZhengzhengLiu #模擬網(wǎng)站,訪問頁(yè)面和部分需要登錄的頁(yè)面,多種認(rèn)證方式 import timer user,passwd = "liu","liu123" def auth(auth_type): print("auth func:",auth_type) def outer_wrapper(func): def wrapper(*args, **kwargs): print("wrapper func args:",*args, **kwargs) if auth_type == "local": username = input("Username:").strip() password = input("Password:").strip() if username == user and password == passwd: print("\033[32;1mUser has passed authentication!\033[0m") #被裝飾的函數(shù)中有返回值,裝飾器中傳入的參數(shù)函數(shù)要有返回值 res = func(*args, **kwargs) #from home print("-----after authentication---") return res else: exit("\033[31;1mInvalid username or password!\033[0m") elif auth_type == "ldap": print("ldap....") return wrapper return outer_wrapper def index(): print("welcome to index page!") @auth(auth_type="local") #利用本地登錄 home = wrapper() def home(): print("welcome to home page!") return "from home" @auth(auth_type="ldap") #利用遠(yuǎn)程的ldap登錄 def bbs(): print("welcome to bbs page!") #函數(shù)調(diào)用 index() print(home()) #wrapper() bbs()
運(yùn)行結(jié)果:
更多關(guān)于Python相關(guān)內(nèi)容可查看本站專題:《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python Socket編程技巧總結(jié)》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》及《Python入門與進(jìn)階經(jīng)典教程》
希望本文所述對(duì)大家Python程序設(shè)計(jì)有所幫助。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。