python之裝飾器

1.認(rèn)識裝飾器

在python中,對于一個函數(shù)京革,若想在其運(yùn)行前后做點(diǎn)什么奇唤,那么裝飾器是再好不過的選擇供璧,話不多說,上代碼冻记。

#!/usr/bin/env
# -*-coding:utf-8-*-
# script: 01.py
__author__ = 'howie'
from functools import wraps
def decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print("%s was called" % func.__name__)
        func(*args, **kwargs)
    return wrapper
@decorator
def hello(name="howie"):
    print("Hello %s!" % name)
hello()
outputs:
hello was called
Hello howie!

這段代碼睡毒,初看之下,確實(shí)不是很理解冗栗,接下來一步一步分析演顾,看看裝飾器到底是怎么工作的。

2.裝飾器原理

在python中隅居,方法允許作為參數(shù)傳遞钠至,想在某個函數(shù)執(zhí)行前后加點(diǎn)料,也可以這樣簡單實(shí)現(xiàn)胎源。

#!/usr/bin/env
# -*-coding:utf-8-*-
# script: 02-1.py
__author__ = 'howie'
def decorator(func):
    print("%s was called" % func.__name__)
    func()
def hello(name="howie"):
    print("Hello %s!" % name)
decorator(hello)

由此棉钧,上面代碼也可以這樣寫:

#!/usr/bin/env
# -*-coding:utf-8-*-
# script: 02-2.py
__author__ = 'howie'
def decorator(func):
    print("%s was called" % func.__name__)
    func()
@decorator
def hello(name="howie"):
    print("Hello %s!" % name)
hello

兩段代碼執(zhí)行后:

outputs:
hello was called
Hello howie!

表面上看來,02-2.py代碼看起來也可以很好地執(zhí)行啊涕蚤,可請注意宪卿,在末尾處,hello只是函數(shù)名稱万栅,它并不能被調(diào)用佑钾,若執(zhí)行hello(),就會報(bào)TypeError: 'NoneType' object is not callable對象不能調(diào)用錯誤烦粒,這是自然休溶,在decoratorfunc()直接將傳入的函數(shù)實(shí)例化了,有人會想扰她,那如果這樣改呢兽掰?

#!/usr/bin/env
# -*-coding:utf-8-*-
# script: 02-3.py
__author__ = 'howie'
def decorator(func):
    print("%s was called" % func.__name__)
    return func
@decorator
def hello(name="howie"):
    print("Hello %s!" % name)
hello()

確實(shí),這樣改是可以徒役,可有沒有想過孽尽,若想在函數(shù)執(zhí)行結(jié)束后加點(diǎn)裝飾呢?這樣便行不通了廉涕,可能又有人會想泻云,若這樣改呢?

#!/usr/bin/env
# -*-coding:utf-8-*-
# script: 02-4.py
__author__ = 'howie'
def decorator(func):
    print("%s was called" % func.__name__)
    func()
    return bye
def bye():
    print("bye~")
@decorator
def hello(name="howie"):
    print("Hello %s!" % name)
hello()

這樣寫看起來狐蜕,恩宠纯,怎么說呢,總有種沒有意義的感覺层释,不如直接將在外部的函數(shù)放進(jìn)decorator中婆瓜,如下:

#!/usr/bin/env
# -*-coding:utf-8-*-
# script: 02-5.py
__author__ = 'howie'
def decorator(func):
    def wrapper():
      print("%s was called" % func.__name__)
      func()
      print("bye~")
    return wrapper
@decorator
def hello(name="howie"):
    print("Hello %s!" % name)
hello()

執(zhí)行:

outputs:
hello was called
Hello howie!
bye~

怎么樣,輸出的結(jié)果是不是符合要求,其實(shí)簡單來看的話廉白,可以這樣理解hello()==decorator(hello)()==wrapper()个初,最后其實(shí)就是執(zhí)行wrapper()函數(shù)而已,事實(shí)就是如此的簡單猴蹂,不妨來驗(yàn)證一下:

#!/usr/bin/env
# -*-coding:utf-8-*-
# script: 02-6.py
__author__ = 'howie'
def decorator(func):
    def wrapper():
      print("%s was called" % func.__name__)
      func()
      print("bye~")
    return wrapper
@decorator
def hello(name="howie"):
    print("Hello %s!" % name)
hello()
print(hello.__name__)
outputs:
hello was called
Hello howie!
bye~
wrapper

果然就是執(zhí)行了wrapper函數(shù)院溺,解決問題的同時也會出現(xiàn)新的問題,那便是代碼中本來定義的hello函數(shù)豈不是被wrapper函數(shù)覆蓋了磅轻,又該如何解決這個問題呢珍逸?這時候functions.wraps就可以登場了,代碼如下:

#!/usr/bin/env
# -*-coding:utf-8-*-
# script: 02-7.py
__author__ = 'howie'
from functools import wraps
def decorator(func):
    @wraps(func)
    def wrapper():
      print("%s was called" % func.__name__)
      func()
      print("bye~")
    return wrapper
@decorator
def hello(name="howie"):
    print("Hello %s!" % name)
hello()
print(hello.__name__)

執(zhí)行代碼:

outputs:
hello was called
Hello howie!
bye~
hello

functions.wraps作用是不是一目了然哈到了這一步聋溜,再看01.py的代碼谆膳,是不是代碼結(jié)構(gòu)清晰明了,只不過多了個參數(shù)

#!/usr/bin/env
# -*-coding:utf-8-*-
# script: 01.py
__author__ = 'howie'
from functools import wraps
def decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print("%s was called" % func.__name__)
        func(*args, **kwargs)
    return wrapper
@decorator
def hello(name="howie"):
    print("Hello %s!" % name)
hello('world')

猜都猜得到執(zhí)行后輸出什么了撮躁。

3.結(jié)語

只要了解裝飾器原理漱病,不管是帶參數(shù)的裝飾器,還是裝飾器類把曼,都是小菜一碟杨帽。
若有錯誤,盡請指出祝迂。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末睦尽,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子型雳,更是在濱河造成了極大的恐慌,老刑警劉巖山害,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纠俭,死亡現(xiàn)場離奇詭異,居然都是意外死亡浪慌,警方通過查閱死者的電腦和手機(jī)冤荆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來权纤,“玉大人钓简,你說我怎么就攤上這事⌒谙耄” “怎么了外邓?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長古掏。 經(jīng)常有香客問我损话,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任丧枪,我火速辦了婚禮光涂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拧烦。我一直安慰自己忘闻,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布恋博。 她就那樣靜靜地躺著齐佳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪交播。 梳的紋絲不亂的頭發(fā)上重虑,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天,我揣著相機(jī)與錄音秦士,去河邊找鬼缺厉。 笑死,一個胖子當(dāng)著我的面吹牛隧土,可吹牛的內(nèi)容都是我干的提针。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼曹傀,長吁一口氣:“原來是場噩夢啊……” “哼辐脖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起皆愉,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤嗜价,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后幕庐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體久锥,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年异剥,在試婚紗的時候發(fā)現(xiàn)自己被綠了瑟由。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡冤寿,死狀恐怖歹苦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情督怜,我是刑警寧澤殴瘦,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站亮蛔,受9級特大地震影響痴施,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一辣吃、第九天 我趴在偏房一處隱蔽的房頂上張望动遭。 院中可真熱鬧,春花似錦神得、人聲如沸厘惦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宵蕉。三九已至,卻和暖如春节榜,著一層夾襖步出監(jiān)牢的瞬間羡玛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工宗苍, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留稼稿,地道東北人。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓讳窟,卻偏偏與公主長得像让歼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子丽啡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評論 2 359

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

  • 前言 Python的修飾器的英文名叫Decorator谋右,當(dāng)你看到這個英文名的時候硫嘶,你可能會把其跟Design Pa...
    linheimx閱讀 632評論 0 4
  • Python之裝飾器 裝飾器本質(zhì)上是一個Python函數(shù)肿嘲,它可以讓其他函數(shù)在不需要做任何代碼變動的前提下增加額外功...
    ikaroskun閱讀 358評論 0 0
  • 裝飾器的作用: 裝飾模式有很多經(jīng)典的使用場景胸梆,例如插入日志抵栈、性能測試、事務(wù)處理等等复斥,有了裝飾器戚丸,就可以提取大量函數(shù)...
    冰西瓜大郎閱讀 226評論 0 0
  • 參考網(wǎng)址> http://www.cnblogs.com/rhcad/archive/2011/12/21/229...
    Alecyrus閱讀 409評論 0 2
  • 像只樹袋熊閱讀 173評論 0 0