類(lèi)裝飾器牍白,裝飾函數(shù)或者類(lèi) 方法

裝飾器類(lèi)懈凹,通用于 function 或 class method
參考: https://stackoverflow.com/questions/1288498/using-the-same-decorator-with-arguments-with-functions-and-methods

先貼上代碼恍风,后面會(huì)有一點(diǎn)解析:

import functools
import time
import logging

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

class call_logger(object):
    """
    Decorator class to log calls on functions or class methods,
    e.g..
        @call_logger
        def my_function():
       class MyClass(object):         
            @call_logger
            def my_method(self):
    """
    def __init__(self, func):
        self._func = func 
        self._wrapped = None
        self._obj = None

    def __call__(self, *args, **kwags):
        if not self._wrapped:
            if self._obj:
                self._wrapped = self._wrap_method(self._func)
                self._wrapped = functools.partial(self._wrapped, self._obj)
            else:
                self._wrapped = self._wrap_function(self._func)
        return self._wrapped(*args, **kwags)

    def __get__(self, obj, type=None):
        self._obj = obj
        return self

    def _wrap_function(self, function):
        """
        Perform the decorator wrapping for a regular function.
        """
        @functools.wraps(function)
        def inner(*args, **kwags):
            """
            Implementation of the wraped function.
            """
            started = time.time()
            exc_name = None
            result = None
            try:
                result = function(*args, **kwags)
            except Exception as ex:
                exc_name = type(ex).__name__
                raise
            finally:
                _log_it(started, function, result, exc_name)
            return result
        return inner

    def _wrap_method(self, method):
        """
        Perform the decorator wrapping for a class method.
        """
        def inner(self, *args, **kwags):
            """
            Implementation of the wrapped function.
            """
            started = time.time()
            exc_name = None
            result = None
            try:
                result = method(self, *args, **kwags)
            except Exception as ex:
                exc_name = type(ex).__name__
                raise
            finally:
                _log_it(started, method, result, exc_name)
        return inner


def _log_it(started, method, result, exc_name):
    finished = time.time()
    elapsed = (finished - started) * 1000
    modname, methname = _get_caller_info(method)
    logging.debug("%s %s takes %s ms", modname, methname, elapsed)


def _get_caller_info(method):
    modname = method.__module__
    methname = method.__name__
    return modname, methname

@call_logger
def test():
    print 'test function'
    time.sleep(1)
    return True

class MyClass(object):

    @call_logger
    def test_method(self):
        time.sleep(1)
        print "test method"

if __name__ == "__main__":
    test()
    test_obj = MyClass()
    test_obj.test_method()
  1. 初始化時(shí)先將 目標(biāo)函數(shù)儲(chǔ)存到裝飾器實(shí)例的私有屬性 _func中,這時(shí)還沒(méi)有進(jìn)行裝飾棒旗。

2 . call 方法的調(diào)用實(shí)際完場(chǎng)了裝飾和執(zhí)行函數(shù)兩個(gè)部分。

  1. get 方法是裝飾通用類(lèi)方法的關(guān)鍵
    當(dāng)裝飾器裝飾上 test_method時(shí)皮壁,此時(shí)的test_method指向的call_logger的實(shí)例對(duì)象椭更。然后通過(guò)test_obj.test_method 時(shí)就觸發(fā)了 get方法,
    傳入test_obj對(duì)象蛾魄,賦給_obj屬性虑瀑,返回call_logger自身的對(duì)象。接著()直接觸發(fā)call方法滴须,裝飾和執(zhí)行目標(biāo)方法舌狗。

  2. 在_wrap_method中,注意inner函數(shù)第一個(gè)參數(shù)要傳入self扔水,因?yàn)檠b飾的是實(shí)例方法痛侍,實(shí)例方法的第一個(gè)參數(shù)為實(shí)例本身。通過(guò)偏函數(shù)來(lái)設(shè)置第一個(gè)默認(rèn)參數(shù)為self._obj

github:
https://github.com/qq915522927/python_enhance/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末魔市,一起剝皮案震驚了整個(gè)濱河市主届,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌待德,老刑警劉巖君丁,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異将宪,居然都是意外死亡绘闷,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)较坛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)印蔗,“玉大人,你說(shuō)我怎么就攤上這事丑勤∮黯” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵确封,是天一觀(guān)的道長(zhǎng)除呵。 經(jīng)常有香客問(wèn)我再菊,道長(zhǎng),這世上最難降的妖魔是什么颜曾? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任纠拔,我火速辦了婚禮,結(jié)果婚禮上泛豪,老公的妹妹穿的比我還像新娘稠诲。我一直安慰自己,他們只是感情好诡曙,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布臀叙。 她就那樣靜靜地躺著,像睡著了一般价卤。 火紅的嫁衣襯著肌膚如雪劝萤。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,036評(píng)論 1 285
  • 那天慎璧,我揣著相機(jī)與錄音床嫌,去河邊找鬼。 笑死胸私,一個(gè)胖子當(dāng)著我的面吹牛厌处,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播岁疼,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼阔涉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了捷绒?” 一聲冷哼從身側(cè)響起瑰排,我...
    開(kāi)封第一講書(shū)人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎疙驾,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體郭毕,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡它碎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了显押。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扳肛。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖乘碑,靈堂內(nèi)的尸體忽然破棺而出挖息,到底是詐尸還是另有隱情,我是刑警寧澤兽肤,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布套腹,位于F島的核電站绪抛,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏电禀。R本人自食惡果不足惜幢码,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望尖飞。 院中可真熱鬧症副,春花似錦、人聲如沸政基。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)沮明。三九已至辕坝,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間珊擂,已是汗流浹背圣勒。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留摧扇,地道東北人圣贸。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像扛稽,于是被迫代替她去往敵國(guó)和親吁峻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉在张,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,679評(píng)論 0 9
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理用含,服務(wù)發(fā)現(xiàn),斷路器帮匾,智...
    卡卡羅2017閱讀 134,599評(píng)論 18 139
  • 楊絮紛飛三月春啄骇,潔身一夢(mèng)踏青云;千里始得西游情瘟斜,古典絕唱留人心缸夹。 楊潔導(dǎo)演 謝謝您給我們一整個(gè)童年的回憶 一路走好!
    方青原閱讀 229評(píng)論 0 0
  • 知道不等于做到 從知道到做到 我們要付出 辛苦的努力螺句,知道不等于做到 沒(méi)它有一個(gè)深入的點(diǎn) 要精 而少 要重復(fù)重復(fù)再...
    請(qǐng)叫我堅(jiān)持閱讀 94評(píng)論 0 1