0101編程-詳解Python裝飾器@

點(diǎn)擊這里進(jìn)入人工智能嘚吧嘚目錄,觀看全部文章


Python中的@操作符稱之為裝飾器decorator['d?k?ret?]抠藕,它用來改變函數(shù)饿肺、方法或類的功能,但又不直接修改它們的代碼盾似,就像錦上添花敬辣,增加新功能,添花但不用去重新織錦零院,所以叫做裝飾器溉跃。

  • 什么是裝飾器@decorator?
  • 參數(shù)怎么通過裝飾器傳遞 args,*kargs告抄?
  • 帶參數(shù)的裝飾器是怎么回事@decorator(x=3)撰茎?
  • 類裝飾器怎么用class decorator?

基本裝飾器

Python中的每個(gè)東西都是對(duì)象打洼,函數(shù)也是個(gè)對(duì)象龄糊,既然是對(duì)象自然就能作為參數(shù)傳遞,也能作為結(jié)果返回募疮,比如:

def decorator(func):  #裝飾函數(shù)炫惩,沒有額外功能
    return func


def div(a, b):  #除法函數(shù)
    return a / b


chufa = decorator(div)  #把div函數(shù)裝飾一下,功能不變
chufa(10, 5)

這個(gè)代碼輸出2.0阿浓。

Python的函數(shù)內(nèi)可以嵌套函數(shù)他嚷,我們把上面代碼修改一下:

def decorator(func):  #裝飾函數(shù),沒有額外功能
    def wrapper(a, b):  #包裹函數(shù),把被除數(shù)放大10倍
        a = a * 10
        return func(a,b)

    return wrapper


def div(a, b):  #除法函數(shù)
    return a / b


chufa = decorator(div)  #把div函數(shù)裝飾一下筋蓖,功能不變
chufa(10, 5)

這個(gè)代碼會(huì)輸出20.0.
它的執(zhí)行順序如下圖:


好了卸耘,我們來把它改為@裝飾器的寫法:

def decorator(func):  #裝飾函數(shù),沒有額外功能
    def wrapper(a, b):  #包裹函數(shù)扭勉,把被除數(shù)放大10倍
        a = a * 10
        return func(a, b)

    return wrapper


@decorator #這句話相當(dāng)于div=decorator(div)
def div(a, b):  #除法函數(shù)
    return a / b


div(10, 5)

輸出結(jié)果仍然是20.0.@decorator這句話就相當(dāng)于div=decorator(div)鹊奖,和上面使用的chufa = decorator(div)是一樣的苛聘,div函數(shù)自身被裝飾了并且覆蓋了原來的div函數(shù)涂炎。

所以我們可以說

@hanshu_A
def hanshu_B(...):
  ...

就是hanshu_B=hanshu_A(hanshu_B),B變?yōu)楸籄裝飾之后的函數(shù)设哗,需要注意的是hanshu_A應(yīng)該接受一個(gè)函數(shù)作為參數(shù)唱捣,并返回一個(gè)函數(shù)作為結(jié)果。

原函數(shù)的參數(shù)

上面例子里wrapper函數(shù)使用了a,b兩個(gè)參數(shù)网梢,為了讓裝飾器函數(shù)decorator更通用震缭,可以使用*args表示任意多個(gè)參數(shù)列表如(1,2,3,4),或者**args表示任意字典對(duì)象參數(shù)如(a=1,b=2,c=3)

修改代碼如下:

def decorator(func):  #裝飾函數(shù)战虏,沒有額外功能
    def wrapper(*args):  #包裹函數(shù)拣宰,把被除數(shù)放大10倍
        return func(args[0]*10,args[1])

    return wrapper


@decorator #這句話相當(dāng)于div=decorator(div)
def div(a, b):  #除法函數(shù)
    return a / b


div(10, 5)

或者:

def decorator(func):  #裝飾函數(shù),沒有額外功能
    def wrapper(**kargs):  #包裹函數(shù)烦感,把被除數(shù)放大10倍
        return func(kargs['a'] * 10, kargs['b'])

    return wrapper


@decorator  #這句話相當(dāng)于div=decorator(div)
def div(a, b):  #除法函數(shù)
    return a / b


div(a=10, b=5)

也可以兩個(gè)連用巡社,保持參數(shù)原封不變傳遞:

def decorator(func):  #裝飾函數(shù),沒有額外功能
    def wrapper(*args, **kargs):  #包裹函數(shù)手趣,把被除數(shù)放大10倍
        print('do nothing...')
        return func(*args, **kargs)

    return wrapper


@decorator  #這句話相當(dāng)于div=decorator(div)
def div(a, b):  #除法函數(shù)
    return a / b


div(a=10, b=5)

@decorator(x=3)帶參數(shù)的裝飾器

簡單說晌该,

@decorator(x=3)
def func(...):
...

就是func=decorator(x=3)(func),這時(shí)候`decorator(x=3)就要返回一個(gè)裝飾器才行绿渣,例如下面將add加法函數(shù)的參數(shù)放大100倍的代碼:

def decorator_big(n):
    def decorator(func):  #裝飾函數(shù)朝群,沒有額外功能
        def wrapper(*args):  #包裹函數(shù),把被除數(shù)放大10倍
            return func(*[x * n for x in args])

        return wrapper

    return decorator


@decorator_big(n=100)  #這句話相當(dāng)于div=decorator(div)
def add(a, b):  #除法函數(shù)
    return a + b


add(10, 5)

輸出[1000,500],1500

類裝飾器

類裝飾器需要定義__init____call__兩個(gè)方法中符,如下:

class my_decorator(object):

    func=None
    def __init__(self, f):
        print("inside my_decorator.__init__()")
        self.func=f

    def __call__(self,*args):
        print("inside my_decorator.__call__()")
        self.func()

@my_decorator
def aFunction():
    print("inside aFunction()")

print('-----')
aFunction()

輸出結(jié)果:

inside my_decorator.__init__()
-----
inside my_decorator.__call__()
inside aFunction()

從這里可以看出

@my_decorator
def aFunction():
...

就是aFunction=my_decorator(aFunction)姜胖,和上面的函數(shù)裝飾器一樣思路,更多內(nèi)容需要讀者多多體會(huì)了淀散。


點(diǎn)擊這里進(jìn)入人工智能DBD嘚吧嘚目錄右莱,觀看全部文章


每個(gè)人的智能新時(shí)代

如果您發(fā)現(xiàn)文章錯(cuò)誤,請(qǐng)不吝留言指正吧凉;
如果您覺得有用隧出,請(qǐng)點(diǎn)喜歡;
如果您覺得很有用阀捅,歡迎轉(zhuǎn)載~


END

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末胀瞪,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌凄诞,老刑警劉巖圆雁,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異帆谍,居然都是意外死亡伪朽,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門汛蝙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來烈涮,“玉大人,你說我怎么就攤上這事窖剑〖崆ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵西土,是天一觀的道長讶舰。 經(jīng)常有香客問我,道長需了,這世上最難降的妖魔是什么跳昼? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮肋乍,結(jié)果婚禮上鹅颊,老公的妹妹穿的比我還像新娘。我一直安慰自己住拭,他們只是感情好挪略,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著滔岳,像睡著了一般杠娱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谱煤,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天摊求,我揣著相機(jī)與錄音,去河邊找鬼刘离。 笑死室叉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的硫惕。 我是一名探鬼主播茧痕,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼恼除!你這毒婦竟也來了踪旷?” 一聲冷哼從身側(cè)響起曼氛,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎令野,沒想到半個(gè)月后舀患,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡气破,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年聊浅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片现使。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡低匙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出朴下,到底是詐尸還是另有隱情努咐,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布殴胧,位于F島的核電站,受9級(jí)特大地震影響佩迟,放射性物質(zhì)發(fā)生泄漏团滥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一报强、第九天 我趴在偏房一處隱蔽的房頂上張望灸姊。 院中可真熱鬧,春花似錦秉溉、人聲如沸力惯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽父晶。三九已至,卻和暖如春弄跌,著一層夾襖步出監(jiān)牢的瞬間甲喝,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來泰國打工铛只, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留埠胖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓淳玩,卻偏偏與公主長得像直撤,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蜕着,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354