Python裝飾器

Python裝飾器

  1. 裝飾器的本質(zhì)是什么?

裝飾器等價于高階函數(shù)疏咐,形如myfunc=decorator(myfunc)纤掸,接受函數(shù)或類作為輸入,以函數(shù)或類作為輸出浑塞。在@語法糖中借跪,并沒有要求輸出為一個函數(shù)或者類。即

def decorator(func):
      return None

@decorator
def foo():
    pass

也可以作為@decorator語法裝飾函數(shù)或類酌壕。
所以掏愁,可以將裝飾器當(dāng)成是一個接受函數(shù)或類為輸入的函數(shù)即可。

  1. 裝飾器的使用場景
  • 插入日志
  • 性能測試
  • 事務(wù)處理
  • 權(quán)限認(rèn)證
  • 修改傳入?yún)?shù)/參數(shù)校驗
  • 結(jié)果預(yù)處理
  • 截斷函數(shù)的執(zhí)行
  1. 編寫不帶裝飾器參數(shù)的裝飾器
def decorator(func):
  # do something when decorator called
    def _deco(*args, **kw):
        # do something before func called
        ret = func(*args, **kw)
        # do something after func called
        return ret
    return _deco

@decorator
def myfunc(*args, **kw):
    print "myfunc called"
    return True

內(nèi)部函數(shù)“_deco”和myfunc的參數(shù)結(jié)構(gòu)需要一致卵牍,當(dāng)然不是要求形式上的一致果港。如參數(shù)為類的裝飾器,如下

def singleton(cls):
    # do something when decorator called
    instances = {}

    def _getinstance(*args, **kw):
        if cls not in instances:
            instances[cls] = cls(*args, **kw)
        return instances[cls]
    return _getinstance

@singleton
class Myclass(object):
    def __init__(self, *args, **kw):
        pass

以上示例為構(gòu)建單例模式的裝飾器版本糊昙。

  1. 編寫帶裝飾器參數(shù)的裝飾器
    帶參數(shù)的裝飾器辛掠,等價于形如myfunc=decorator(a, b)(myfunc)的函數(shù)調(diào)用。decorator(a, b)返回一個不帶裝飾器參數(shù)的裝飾器释牺,即過程為:decorator1 = decorator(a, b) 萝衩;myfunc = decorator1(myfunc)。形式上多了一層函數(shù)没咙,不過也可以使用柯里化的方式構(gòu)建decorator1猩谊。如下例:
from functools import partial

def decorator(a, func):
    # do something when decorator called
    def _deco(*args, **kw):
        # do something before func called
        ret = func(*args, **kw)
        # do something after func called
        return ret
    return _deco
# or

def decorator_out(*args, **kwargs):
    # do something when decorator_out called with parameters
    def _outer(func):
        # do something when decorator_out called
        def _deco(*arg, **kw):
            # do something before func called
            # of course `*args` or `**kwargs`
            ret = func(*arg, **kw)
            # do something after func called
        return _deco
    return _outer

@partial(decorator, "param1")
def myfunc():
    print "myfunc"

@decorator_out("params1")
def myfunc1():
  print "myfunc1"
  1. functools.wraps
    因為Python中__name____doc__等metadata是在函數(shù)定義中生成的,而無法在執(zhí)行過程中生成祭刚,所以myfunc=decorator(myfunc)執(zhí)行之后牌捷,myfunc的metadata會發(fā)生變化队塘,如myfunc.__name__,解決方案是裝飾器中宜鸯,加上functools.wraps憔古。如上例:
from functools import wraps

def decorator_out(*args, **kwargs):
    # do something when decorator_out called with parameters
    def _outer(func):
        # do something when decorator_out called
        @wraps(func)
        def _deco(*arg, **kw):
            # do something before func called
            # of course `*args` or `**kwargs`
            ret = func(*arg, **kw)
            # do something after func called
            return ret
        return _deco
    return _outer
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市淋袖,隨后出現(xiàn)的幾起案子鸿市,更是在濱河造成了極大的恐慌,老刑警劉巖即碗,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件焰情,死亡現(xiàn)場離奇詭異,居然都是意外死亡剥懒,警方通過查閱死者的電腦和手機(jī)内舟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來初橘,“玉大人验游,你說我怎么就攤上這事”i埽” “怎么了耕蝉?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長夜只。 經(jīng)常有香客問我垒在,道長,這世上最難降的妖魔是什么扔亥? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任场躯,我火速辦了婚禮,結(jié)果婚禮上旅挤,老公的妹妹穿的比我還像新娘踢关。我一直安慰自己,他們只是感情好谦铃,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布耘成。 她就那樣靜靜地躺著,像睡著了一般驹闰。 火紅的嫁衣襯著肌膚如雪瘪菌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天嘹朗,我揣著相機(jī)與錄音师妙,去河邊找鬼。 笑死屹培,一個胖子當(dāng)著我的面吹牛默穴,可吹牛的內(nèi)容都是我干的怔檩。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼蓄诽,長吁一口氣:“原來是場噩夢啊……” “哼薛训!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起仑氛,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤乙埃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后锯岖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體介袜,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年出吹,在試婚紗的時候發(fā)現(xiàn)自己被綠了遇伞。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡捶牢,死狀恐怖鸠珠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情叫确,我是刑警寧澤跳芳,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站竹勉,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏娄琉。R本人自食惡果不足惜次乓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望孽水。 院中可真熱鬧票腰,春花似錦、人聲如沸女气。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽炼鞠。三九已至缘滥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谒主,已是汗流浹背朝扼。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留霎肯,地道東北人擎颖。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓榛斯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親搂捧。 傳聞我的和親對象是個殘疾皇子驮俗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評論 2 361

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