python07_函數(shù)裝飾器

函數(shù)裝飾器

  1. 為什么要用裝飾器?

    裝飾器本質(zhì)上是一個(gè)函數(shù),該函數(shù)用來處理其他函數(shù),它可以讓其他函數(shù)在不需要修改代碼的前提下增加額外的功能卷要,裝飾器的返回值也是一個(gè)函數(shù)對(duì)象。它經(jīng)常用于有切面需求的場景独榴,比如:插入日志僧叉、性能測(cè)試、事務(wù)處理棺榔、緩存瓶堕、權(quán)限校驗(yàn)等應(yīng)用場景。裝飾器是解決這類問題的絕佳設(shè)計(jì)症歇,有了裝飾器郎笆,我們就可以抽離出大量與函數(shù)功能本身無關(guān)的雷同代碼并繼續(xù)重用.概括的講,裝飾器的作用就是為已經(jīng)存在的對(duì)象添加額外的功能忘晤。

  2. 先定義兩個(gè)個(gè)函數(shù)

         def addUser():
             print('添加用戶成功宛蚓!')
    
         def registUser():
             print('添加用戶成功!')
    

    如果用戶想要知道是哪個(gè)函數(shù)添加了用戶设塔,怎么辦凄吏?(略...)

    改進(jìn)方法

         def debug():
             import inspect
             caller_name = inspect.stack()[1][3]
             print("[DEBUG]: enter {}()".format(caller_name))
         
         def addUser():
             debug()
             print('添加用戶成功!')
         
         def registUser():
             debug()
             print('添加用戶成功!')
    

    但是如果再想要取消這個(gè)功能痕钢,則需要改變兩個(gè)函數(shù):addUser表谊,registUser

     **裝飾器的作用很明顯**
         
         def debug(func):
             def wrapper():
                 print("[DEBUG]: enter {}()".format(func.__name__))
                 return func()
             return wrapper
         
         @debug
         def addUser():
             print('添加用戶成功!')
             return 'ok'
         
         @debug
         def registUser():
             print('添加用戶成功盖喷!')
    
  3. 裝飾器傳參

    參數(shù)先傳給裝飾器,裝飾器傳給函數(shù)

     def debug(func):
         def wrapper(name):
             print("[DEBUG]: enter {}()".format(func.__name__))
             func(name)
         return wrapper
     
     @debug
     def addUser(name):
         print('添加用戶{0}成功难咕!'.format(name))
     
     @debug
     def registUser(name):
         print('添加用戶{0}成功课梳!'.format(name))
     
     addUser('tom')
     registUser('jack')
    

    如果函數(shù)是有返回值的,則加上return 語句即可

     def debug(func):
         def wrapper(name):
             print("[DEBUG]: enter {}()".format(func.__name__))
             return func(name)  #此處加上return
         return wrapper
    
  4. 傳遞可變參數(shù)

     def debug(func):
         def wrapper(*args,**other):
             print("[DEBUG]: enter {}()".format(func.__name__))
             print(other)
             # 可以在此處對(duì) args和other數(shù)據(jù)進(jìn)行處理
             return func(args)
         return wrapper
     
     @debug
     def addUser(user):
         print('添加用戶{0}成功余佃!'.format(user))
         return user
     
     @debug
     def registUser(user):
         print('添加用戶{0}成功暮刃!'.format(user))
         return user
     
     n1=addUser('tom',12,other={'gender': 'M', 'job': 'Engineer'})
     n2=registUser('jack')
    
  5. 最新版本

    最新版本的python導(dǎo)入了functools模塊

     from functools import wraps
     def debug(func):
         @wraps(func)
         def wrapper(name):
             print("[DEBUG]: enter {}()".format(func.__name__))
             return func(name)  #此處加上return
         return wrapper
     @debug
     
     def show(s):
         print(s)
     
     show('ppyth')
    
  6. 帶參數(shù)的裝飾器

        from functools import wraps
        def debug(*text):
            def decorated(func):
                @wraps(func)
                def wrapper(name):
                    print("[DEBUG]: enter {}()".format(func.__name__))
                    return func(name)  # 此處加上return
        
                return wrapper
            return decorated
        
        @debug()  #此處的()不可以刪略
        def show(s):
            print(s)
        
        show('ppyth')
    
  7. __call__()

    所有的函數(shù)都是可調(diào)用對(duì)象。
    一個(gè)類實(shí)例也可以變成一個(gè)可調(diào)用對(duì)象爆土,只需要實(shí)現(xiàn)一個(gè)特殊方法call()

     class Person(object):
         def __init__(self,name):
             self.name=name
     
         def __call__(self, *args, **kwargs):
             print('my name is ',self.name)
             print('my hobby is ',args)
     
     p1=Person('tom')
     
     p1('reading')
    

    所以椭懊,在Python中,函數(shù)也是對(duì)象步势,對(duì)象和函數(shù)的區(qū)別并不顯著氧猬。

  8. 類裝飾器(待續(xù).....)

     from functools import wraps
     from datetime import datetime
     
     #類的裝飾器寫法,日志
     class log(object):
         def __init__(self, logfile='out.log'):
             self.logfile = logfile
     
         def __call__(self, func):
             @wraps(func)
             def wrapped_func(*args, **kwargs):                     
                 self.writeLog(*args, **kwargs)    # 先調(diào)用 寫入日志         
                 return func(*args, **kwargs)     # 正式調(diào)用主要處理函數(shù)       
             return wrapped_func
     
        #寫入日志    
         def writeLog(self, *args, **kwargs):
             time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
             log_str = time+' 操作人:{0[0]} 進(jìn)行了【{0[1]}】操作'.format(args)           
             with open(self.logfile, 'a',encoding='utf8') as file:
                 file.write(log_str + '\n')
     
     @log()
     def myfunc(name,age):
         print('姓名:{0},年齡:{1}'.format(name,age))
     
     if __name__ == '__main__':
         myfunc('小白', '查詢')
         myfunc('root', '添加人員')
         myfunc('小小', '修改數(shù)據(jù)')
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末坏瘩,一起剝皮案震驚了整個(gè)濱河市盅抚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌倔矾,老刑警劉巖妄均,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異哪自,居然都是意外死亡丰包,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門壤巷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來邑彪,“玉大人,你說我怎么就攤上這事胧华⌒啃睿” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵撑柔,是天一觀的道長瘸爽。 經(jīng)常有香客問我,道長铅忿,這世上最難降的妖魔是什么剪决? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上柑潦,老公的妹妹穿的比我還像新娘享言。我一直安慰自己,他們只是感情好渗鬼,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布览露。 她就那樣靜靜地躺著,像睡著了一般譬胎。 火紅的嫁衣襯著肌膚如雪差牛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天堰乔,我揣著相機(jī)與錄音偏化,去河邊找鬼。 笑死镐侯,一個(gè)胖子當(dāng)著我的面吹牛侦讨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播苟翻,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼韵卤,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了崇猫?” 一聲冷哼從身側(cè)響起怜俐,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎邓尤,沒想到半個(gè)月后拍鲤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡汞扎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年季稳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片澈魄。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡景鼠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出痹扇,到底是詐尸還是另有隱情铛漓,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布鲫构,位于F島的核電站浓恶,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏结笨。R本人自食惡果不足惜包晰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一湿镀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧伐憾,春花似錦勉痴、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至胸嘴,卻和暖如春雏掠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背筛谚。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留停忿,地道東北人驾讲。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像席赂,于是被迫代替她去往敵國和親吮铭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 寫在前面的話 代碼中的# > 表示的是輸出結(jié)果 輸入 使用input()函數(shù) 用法 注意input函數(shù)輸出的均是字...
    FlyingLittlePG閱讀 2,771評(píng)論 0 8
  • 一颅停、裝飾器的基本使用 在不改變函數(shù)源代碼的前提下谓晌,給函數(shù)添加新的功能,這時(shí)就需要用到“裝飾器”癞揉。 0.開放封閉原則...
    NJingZYuan閱讀 530評(píng)論 0 0
  • 裝飾器本質(zhì)上是一個(gè)函數(shù)纸肉,該函數(shù)用來處理其他函數(shù),它可以讓其他函數(shù)在不需要修改代碼的前提下增加額外的功能喊熟,裝飾器的返...
    胡一巴閱讀 418評(píng)論 0 0
  • 本文的目錄如下:裝飾器語法糖入門用法:日志打印器入門用法:時(shí)間計(jì)時(shí)器進(jìn)階用法:帶參數(shù)的函數(shù)裝飾器高階用法:不帶參數(shù)...
    A遇上方知友閱讀 754評(píng)論 0 0
  • 在python編程中柏肪,我們經(jīng)常看到下面的函數(shù)用法: with open("test.txt", "w") as f...
    hugoren閱讀 829評(píng)論 0 0