Python裝飾器原理與用法分析
本文實(shí)例講述了Python裝飾器原理與用法。分享給大家供大家參考,具體如下:
1、裝飾器的本質(zhì)是函數(shù),主要用來(lái)裝飾其他函數(shù),也就是為其他函數(shù)添加附加功能
2、裝飾器的原則:
(1) 裝飾器不能修改被裝飾的函數(shù)的源代碼
(2) 裝飾器不能修改被裝飾的函數(shù)的調(diào)用方式
3、實(shí)現(xiàn)裝飾器的知識(shí)儲(chǔ)備
(1) Python中函數(shù)即‘變量'
a、變量在Python中的存儲(chǔ)
x='Tomwenxing' y=x
[說(shuō)明]:
當(dāng)Python解釋器遇到語(yǔ)句x='Tomwenxing'時(shí),它主要完成了兩樣工作:
1.在內(nèi)存中開(kāi)辟了一片空間用來(lái)存儲(chǔ)字符串‘Tomwenxing'
2.在內(nèi)存從創(chuàng)建了一個(gè)名為x的變量,并用它指向字符串‘Tomwenxing'所占據(jù)的內(nèi)存空間(可以理解為房間和房間號(hào)的關(guān)系)
而語(yǔ)句y=x意為將變量x對(duì)字符串的引用賦值給變量y,即在內(nèi)存中創(chuàng)建一個(gè)變量y,并使其指向變量x所指向的內(nèi)存空間
b、函數(shù)在Python中的存儲(chǔ)
def test(): pass
[說(shuō)明]:
在Python中,函數(shù)的存儲(chǔ)和變量相似,以上面的函數(shù)為例,Python解釋其主要做兩件事:
1.在內(nèi)存中開(kāi)辟一個(gè)內(nèi)存空間,用來(lái)存儲(chǔ)函數(shù)代碼的字符串(本例中代碼只有一句:pass)
2.在內(nèi)存中創(chuàng)建一個(gè)變量test,用來(lái)指向存儲(chǔ)函數(shù)代碼字符串的內(nèi)存空間(相當(dāng)于test=‘函數(shù)體')
因此說(shuō)在Python中函數(shù)即變量
(2) 高階函數(shù)(下面兩個(gè)條件滿足任何一個(gè)即為高階函數(shù))
a、把一個(gè)函數(shù)名當(dāng)做實(shí)參傳遞給另外一個(gè)函數(shù)
[對(duì)裝飾器的影響]:達(dá)到“在不修改被裝飾函數(shù)源代碼的情況下為其添加功能”的效果
import time def bar(): time.sleep(2) print('in the bar') def test(func): start_time=time.time() func() stop_time=time.time() print('函數(shù)的運(yùn)行時(shí)間為:',stop_time-start_time) test(bar)
運(yùn)行結(jié)果:
in the bar
函數(shù)的運(yùn)行時(shí)間為: 2.0021145343780518
b、返回值中包含函數(shù)名
[對(duì)裝飾器的影響]:達(dá)到“不改變函數(shù)的調(diào)用方式“的效果
import time def bar(): time.sleep(3) print('in the bar') def test2(func): print('新添加的功能') return func bar=test2(bar) bar()
運(yùn)行結(jié)果:
新添加的功能
in the bar
(3) 嵌套函數(shù):在一個(gè)函數(shù)體內(nèi)用def去聲明一個(gè)新的函數(shù)(不是調(diào)用)
def foo(): print('in the foo') def bar(): #聲明一個(gè)新的函數(shù),而不是調(diào)用函數(shù) print('in the bar') bar() foo()
運(yùn)行結(jié)果:
in the foo
in the bar
4、裝飾器的語(yǔ)法:高階函數(shù)+嵌套函數(shù)=》裝飾器 (下面的例子可以用pycharm的調(diào)試器調(diào)試一下,看看代碼的運(yùn)行順序)
import time def timer(func): def deco(*args,**kwargs):#使用了不定參數(shù) start_time=time.time() res=func(*args,**kwargs) #運(yùn)行函數(shù) stop_time=time.time() print('運(yùn)行時(shí)間:',stop_time-start_time) return res # 若無(wú)返回值,則返回None return deco @timer #等價(jià)于test1=timer(test1)=deco,即test1()=deco() def test1(): time.sleep(3) print('in the test1') @timer #等價(jià)于test2=timer(test2)=deco,即test2(name)=deco(name) def test2(name): time.sleep(3) print('in the test2',name) test1() print('-------------分界線------------------------') test2('Tomwenxing')
運(yùn)行結(jié)果:
in the test1
運(yùn)行時(shí)間: 3.0001718997955322
-------------分界線------------------------
in the test2 Tomwenxing
運(yùn)行時(shí)間: 3.000171422958374
5、帶參數(shù)的裝飾器
# -*- coding:utf-8 -*- user,passwd='Tomwenxing','123' #如裝飾器帶參數(shù),一般是三層嵌套 def auth(auth_type): #第一層的參數(shù)是裝飾器的參數(shù) def outer_wrapper(func):#第二層的參數(shù)是裝飾器要裝飾的目標(biāo)函數(shù) def wrapper(*args,**kwargs):#第三次的參數(shù)是目標(biāo)函數(shù)的參數(shù) if auth_type=='local': username = input('Username:').strip() password = input('Password:').strip() if user == username and passwd == password: print('用戶Tomwenxing已經(jīng)成功登錄!') res = func(*args, **kwargs) #運(yùn)行目標(biāo)函數(shù) return res else: exit('用戶名或密碼有錯(cuò)誤') elif auth_type=='ldap': print('暫不支持這種登錄方式!') return wrapper return outer_wrapper def index(): print('歡迎來(lái)到index頁(yè)面') @auth(auth_type='local') #home=wrapper() def home(name): print('%s,歡迎來(lái)到home頁(yè)面' %name) return 'This is home page' @auth(auth_type='ldap') def bbs(): print('歡迎來(lái)到bbs頁(yè)面 ') index() print('----------------------分界線-------------------') print('函數(shù)的返回值為:',home('wenxing')) print('----------------------分界線-------------------') bbs()
運(yùn)行結(jié)果:
歡迎來(lái)到index頁(yè)面
----------------------分界線-------------------
Username:Tomwenxing
Password:123
用戶Tomwenxing已經(jīng)成功登錄!
wenxing,歡迎來(lái)到home頁(yè)面
函數(shù)的返回值為: This is home page
----------------------分界線-------------------
暫不支持這種登錄方式!
更多關(guān)于Python相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python加密解密算法與技巧總結(jié)》、《Python編碼操作技巧總結(jié)》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》及《Python入門與進(jìn)階經(jīng)典教程》
希望本文所述對(duì)大家Python程序設(shè)計(jì)有所幫助。
相關(guān)文章
如何通過(guò)Python3和ssl實(shí)現(xiàn)加密通信功能
這篇文章主要介紹了如何通過(guò)Python3和ssl實(shí)現(xiàn)加密通信功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05Python如何使用qrcode生成指定內(nèi)容的二維碼并在GUI界面顯示
現(xiàn)在二維碼很流行,大街小巷大小商品廣告上的二維碼標(biāo)簽都隨處可見(jiàn),下面這篇文章主要給大家介紹了關(guān)于如何使用qrcode生成指定內(nèi)容的二維碼并在GUI界面顯示的相關(guān)資料,需要的朋友可以參考下2022-09-09python爬蟲(chóng) 批量下載zabbix文檔代碼實(shí)例
這篇文章主要介紹了python爬蟲(chóng) 批量下載zabbix文檔代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08Python3非對(duì)稱加密算法RSA實(shí)例詳解
這篇文章主要介紹了Python3非對(duì)稱加密算法RSA,結(jié)合實(shí)例形式分析了Python3 RSA加密相關(guān)模塊安裝及使用操作技巧,需要的朋友可以參考下2018-12-12Python如何通過(guò)subprocess調(diào)用adb命令詳解
python可以說(shuō)是寫(xiě)一些小腳本的利器語(yǔ)法簡(jiǎn)單,做為最著名的就“膠水語(yǔ)言”用它來(lái)寫(xiě)一些命令腳本非常的方便。下面這篇文章主要給大家介紹了關(guān)于Python如何通過(guò)subprocess調(diào)用adb命令的相關(guān)資料,需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-08-08Python爬蟲(chóng)自動(dòng)化爬取b站實(shí)時(shí)彈幕實(shí)例方法
在本篇文章里小編給大家整理的是一篇關(guān)于Python爬蟲(chóng)自動(dòng)化爬取b站實(shí)時(shí)彈幕實(shí)例方法,有興趣的朋友們可以學(xué)習(xí)下。2021-01-01Python寫(xiě)入數(shù)據(jù)到MP3文件中的方法
這篇文章主要介紹了Python寫(xiě)入數(shù)據(jù)到MP3文件中的方法,可實(shí)現(xiàn)將MP3文件相關(guān)信息寫(xiě)入MP3文件的功能,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07Python實(shí)現(xiàn)短網(wǎng)址ShortUrl的Hash運(yùn)算實(shí)例講解
這篇文章主要介紹了Python實(shí)現(xiàn)短網(wǎng)址ShortUrl的Hash運(yùn)算,較為詳細(xì)的分析了Python短網(wǎng)址運(yùn)算的算法原理與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2015-08-08