python裝飾器代碼解析
1.裝飾器通用模型
def wrapper(fn): ? ? def inner(*args, **kwargs): ? ? ? ? ret = fn(*args, **kwargs) ? ? ? ? return ret ? ? return inner
裝飾器幾個關(guān)鍵點:
- 1.函數(shù)可以當(dāng)參數(shù)傳遞
- 2.函數(shù)可以作為返回值進行返回
- 3.函數(shù)名稱可以當(dāng)成變量一樣進行賦值操作
裝飾器本質(zhì)上是個閉包,在不改變原有函數(shù)調(diào)用的情況下,給函數(shù)增加新的功能
舉個例子:
def admin(game): ? ? def inner(*args, **kwargs): ?# inner添加了參數(shù),args 一定是個元組 kwargs 一定是字典 ? ? ? ? print('打開Wg') ? ? ? ? result = game(*args, **kwargs) ?# * ** 表示把args元組和kwargs打散成位置參數(shù),關(guān)鍵字參數(shù)傳遞進去 ? ? ? ? print('關(guān)閉Wg') ? ? ? ? return result ? ? return inner @admin def play_dnf(username, password): ? ? print(f'開始玩DNF,賬號:{username},密碼:{password}') ? ? print('刀斬肉身,心斬靈魂') ? ? return '掉落:戮蠱的哀鳴炮' @admin def play_wow(race, occupation, server_name, camp): ? ? print(f'開始玩魔獸世界,種族:{race},職業(yè):{occupation},服務(wù)器:{server_name},陣營:{camp}') ? ? print('為了辛多雷的榮耀') ? ? return '掉落:灰燼使者' if __name__ == '__main__': ? ? ret1 = play_dnf('大馬猴', '888888') ? ? print(ret1) ? ? ret2 = play_wow('血精靈', '圣騎士', '回音山', '部落') ? ? print(ret2)
這代碼還是很好懂的,我就不解釋了,然后是執(zhí)行結(jié)果如下:
python demo.py
打開Wg
開始玩DNF,賬號:大馬猴,密碼:888888
刀斬肉身,心斬靈魂
關(guān)閉Wg
掉落:戮蠱的哀鳴炮
打開Wg
開始玩魔獸世界,種族:血精靈,職業(yè):圣騎士,服務(wù)器:回音山,陣營:部落
為了辛多雷的榮耀
關(guān)閉Wg
掉落:灰燼使者Process finished with exit code 0
2.多個裝飾器裝飾的函數(shù)執(zhí)行
一個函數(shù)被多個裝飾器裝飾,又將如何執(zhí)行呢?
def wrapper1(fn): ? ? def inner(*args, **kwargs): ? ? ? ? print('這是w1進入') ? ? ? ? ret = fn(*args, **kwargs) ? ? ? ? print('這是w1出去') ? ? ? ? return ret ? ? return inner def wrapper2(fn): ? ? def inner(*args, **kwargs): ? ? ? ? print('這是w2進入') ? ? ? ? ret = fn(*args, **kwargs) ? ? ? ? print('這是w2出去') ? ? ? ? return ret ? ? return inner @wrapper1 @wrapper2 def target(): ? ? print('我是目標') if __name__ == '__main__': ? ? target()
直接給出執(zhí)行順序:
一個函數(shù)被多個裝飾器裝飾的執(zhí)行順序
# w1 w2 target w2 w1
3.帶參數(shù)的裝飾器
裝飾器的語法允許我們在調(diào)用時,提供其它參數(shù),比如@decorator(a)。這樣,就為裝飾器的編寫和使用提供了更大的靈活性。
(在上面又套了一層函數(shù))
比如,我們可以在裝飾器中指定日志的等級,因為不同業(yè)務(wù)函數(shù)可能需要的日志級別是不一樣的。
def use_logging(level): ? ? def decorator(func): ? ? ? ? def wrapper(*args, **kwargs): ? ? ? ? ? ? if level == "warn": ? ? ? ? ? ? ? ? logging.warn("%s is running" % func.__name__) ? ? ? ? ? ? elif level == "info": ? ? ? ? ? ? ? ? logging.info("%s is running" % func.__name__) ? ? ? ? ? ? return func(*args) ? ? ? ? return wrapper ? ? return decorator @use_logging(level="warn") def foo(name='foo'): ? ? print("i am %s" % name) foo()
4.類裝飾器
沒錯,裝飾器不僅可以是函數(shù),還可以是類,相比函數(shù)裝飾器,類裝飾器具有靈活度大、高內(nèi)聚、封裝性等優(yōu)點。使用類裝飾器主要依靠類的__call__
方法,當(dāng)使用 @ 形式將裝飾器附加到函數(shù)上時,就會調(diào)用此方法。
class Foo(object): ? ? def __init__(self, func): ? ? ? ? self._func = func ? ? def __call__(self): ? ? ? ? print ('class decorator runing') ? ? ? ? self._func() ? ? ? ? print ('class decorator ending') @Foo def bar(): ? ? print ('bar') bar()
到此這篇關(guān)于python裝飾器代碼解析的文章就介紹到這了,更多相關(guān)python裝飾器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python實現(xiàn)網(wǎng)頁文件轉(zhuǎn)PDF文件和PNG圖片的示例代碼
這篇文章主要介紹了如何利用Python分別實現(xiàn)網(wǎng)頁文件轉(zhuǎn)為PDF文件和網(wǎng)頁文件轉(zhuǎn)PNG圖片的示例代碼,文中的代碼簡潔易懂,感興趣的可以動手試試2022-01-01在tensorflow下利用plt畫論文中l(wèi)oss,acc等曲線圖實例
這篇文章主要介紹了在tensorflow下利用plt畫論文中l(wèi)oss,acc等曲線圖實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-06-06Python的Django框架中的數(shù)據(jù)過濾功能
這篇文章主要介紹了Python的Django框架中的數(shù)據(jù)過濾功能,為更新數(shù)據(jù)庫數(shù)據(jù)時的數(shù)據(jù)查找提供了方便,需要的朋友可以參考下2015-07-07python?NetworkX庫生成并繪制帶權(quán)無向圖
這篇文章主要為大家介紹了python?NetworkX庫生成并繪制帶權(quán)無向圖的實現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05