>> def now(): ... print '2013-12-25' ... >>> f = now >>> f() 2013-12-25 函數對象有一個__name__屬性,可以拿到函數的名字: >>> now._" />

<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        舉例講解Python中裝飾器的用法

        來源:懂視網 責編:小采 時間:2020-11-27 14:39:28
        文檔

        舉例講解Python中裝飾器的用法

        舉例講解Python中裝飾器的用法:由于函數也是一個對象,而且函數對象可以被賦值給變量,所以,通過變量也能調用該函數。 >>> def now(): ... print '2013-12-25' ... >>> f = now >>> f() 2013-12-25 函數對象有一個__name__屬性,可以拿到函數的名字: >>> now._
        推薦度:
        導讀舉例講解Python中裝飾器的用法:由于函數也是一個對象,而且函數對象可以被賦值給變量,所以,通過變量也能調用該函數。 >>> def now(): ... print '2013-12-25' ... >>> f = now >>> f() 2013-12-25 函數對象有一個__name__屬性,可以拿到函數的名字: >>> now._

        由于函數也是一個對象,而且函數對象可以被賦值給變量,所以,通過變量也能調用該函數。

        >>> def now():
        ... print '2013-12-25'
        ...
        >>> f = now
        >>> f()
        2013-12-25
        
        

        函數對象有一個__name__屬性,可以拿到函數的名字:

        >>> now.__name__
        'now'
        >>> f.__name__
        'now'
        
        

        現在,假設我們要增強now()函數的功能,比如,在函數調用前后自動打印日志,但又不希望修改now()函數的定義,這種在代碼運行期間動態增加功能的方式,稱之為“裝飾器”(Decorator)。

        本質上,decorator就是一個返回函數的高階函數。所以,我們要定義一個能打印日志的decorator,可以定義如下:

        def log(func):
         def wrapper(*args, **kw):
         print 'call %s():' % func.__name__
         return func(*args, **kw)
         return wrapper
        
        

        觀察上面的log,因為它是一個decorator,所以接受一個函數作為參數,并返回一個函數。我們要借助Python的@語法,把decorator置于函數的定義處:

        @log
        def now():
         print '2013-12-25'
        
        

        調用now()函數,不僅會運行now()函數本身,還會在運行now()函數前打印一行日志:

        >>> now()
        call now():
        2013-12-25
        
        

        把@log放到now()函數的定義處,相當于執行了語句:

        now = log(now)
        
        

        由于log()是一個decorator,返回一個函數,所以,原來的now()函數仍然存在,只是現在同名的now變量指向了新的函數,于是調用now()將執行新函數,即在log()函數中返回的wrapper()函數。

        wrapper()函數的參數定義是(*args, **kw),因此,wrapper()函數可以接受任意參數的調用。在wrapper()函數內,首先打印日志,再緊接著調用原始函數。

        如果decorator本身需要傳入參數,那就需要編寫一個返回decorator的高階函數,寫出來會更復雜。比如,要自定義log的文本:

        def log(text):
         def decorator(func):
         def wrapper(*args, **kw):
         print '%s %s():' % (text, func.__name__)
         return func(*args, **kw)
         return wrapper
         return decorator
        
        

        這個3層嵌套的decorator用法如下:

        @log('execute')
        def now():
         print '2013-12-25'
        
        

        執行結果如下:

        >>> now()
        execute now():
        2013-12-25
        
        

        和兩層嵌套的decorator相比,3層嵌套的效果是這樣的:

        >>> now = log('execute')(now)
        
        

        我們來剖析上面的語句,首先執行log('execute'),返回的是decorator函數,再調用返回的函數,參數是now函數,返回值最終是wrapper函數。

        以上兩種decorator的定義都沒有問題,但還差最后一步。因為我們講了函數也是對象,它有__name__等屬性,但你去看經過decorator裝飾之后的函數,它們的__name__已經從原來的'now'變成了'wrapper':

        >>> now.__name__
        'wrapper'
        
        

        因為返回的那個wrapper()函數名字就是'wrapper',所以,需要把原始函數的__name__等屬性復制到wrapper()函數中,否則,有些依賴函數簽名的代碼執行就會出錯。

        不需要編寫wrapper.__name__ = func.__name__這樣的代碼,Python內置的functools.wraps就是干這個事的,所以,一個完整的decorator的寫法如下:

        import functools
        
        def log(func):
         @functools.wraps(func)
         def wrapper(*args, **kw):
         print 'call %s():' % func.__name__
         return func(*args, **kw)
         return wrapper
        
        

        或者針對帶參數的decorator:

        import functools
        
        def log(text):
         def decorator(func):
         @functools.wraps(func)
         def wrapper(*args, **kw):
         print '%s %s():' % (text, func.__name__)
         return func(*args, **kw)
         return wrapper
         return decorator
        
        

        import functools是導入functools模塊。模塊的概念稍候講解。現在,只需記住在定義wrapper()的前面加上@functools.wraps(func)即可。
        小結

        在面向對象(OOP)的設計模式中,decorator被稱為裝飾模式。OOP的裝飾模式需要通過繼承和組合來實現,而Python除了能支持OOP的decorator外,直接從語法層次支持decorator。Python的decorator可以用函數實現,也可以用類實現。

        decorator可以增強函數的功能,定義起來雖然有點復雜,但使用起來非常靈活和方便。

        請編寫一個decorator,能在函數調用的前后打印出'begin call'和'end call'的日志。

        再思考一下能否寫出一個@log的decorator,使它既支持:

        @log
        def f():
         pass
        
        

        又支持:

        @log('execute')
        def f():
         pass
        
        

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        舉例講解Python中裝飾器的用法

        舉例講解Python中裝飾器的用法:由于函數也是一個對象,而且函數對象可以被賦值給變量,所以,通過變量也能調用該函數。 >>> def now(): ... print '2013-12-25' ... >>> f = now >>> f() 2013-12-25 函數對象有一個__name__屬性,可以拿到函數的名字: >>> now._
        推薦度:
        標簽: 使用 用法 使用的
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 国产免费AV片在线观看播放| 100部毛片免费全部播放完整| 啦啦啦手机完整免费高清观看 | 蜜桃AV无码免费看永久| 亚洲av午夜福利精品一区| 伊人久久大香线蕉免费视频| 在线日韩日本国产亚洲| 成人免费区一区二区三区 | 亚洲一区二区三区高清在线观看 | 18观看免费永久视频| 亚洲高清美女一区二区三区| 57pao一国产成视频永久免费 | 国产精品亚洲一区二区在线观看| 成人午夜18免费看| 国产精品亚洲精品日韩电影| 大胆亚洲人体视频| 国产偷伦视频免费观看| 亚洲高清在线播放| 69天堂人成无码麻豆免费视频| 亚洲噜噜噜噜噜影院在线播放| 一级毛片免费播放试看60分钟| 亚洲成?Ⅴ人在线观看无码| 岛国精品一区免费视频在线观看 | 免费看少妇高潮成人片| 久久久亚洲欧洲日产国码农村| 99国产精品永久免费视频| 色婷婷亚洲一区二区三区| 亚洲中文字幕无码久久2017| 最近免费视频中文字幕大全| 亚洲小说图区综合在线| 亚洲情侣偷拍精品| 67pao强力打造国产免费| 亚洲一卡一卡二新区无人区| 中文国产成人精品久久亚洲精品AⅤ无码精品 | 亚洲综合国产一区二区三区| 99精品视频在线观看免费播放| 日本亚洲国产一区二区三区| 99热精品在线免费观看| 激情小说亚洲色图| 久久精品国产亚洲AV麻豆不卡 | 亚洲欧洲日本国产|