姓名:樂仁華 學(xué)號:16140220023
轉(zhuǎn)載自:
【嵌牛導(dǎo)讀】:本文主要是介紹python中裝飾器的作用
【嵌牛鼻子】:python , 裝飾器
【嵌牛提問】:python的裝飾器是什么?有什么用?
【嵌牛正文】:
我想許多剛學(xué)python不久的同學(xué)見到@這樣的符號,都會有些不知所以的感覺,我剛開始遇到時也一臉茫然,后面在網(wǎng)上查了一下說@符號是裝飾器的語法糖,那么問題來了,裝飾器是啥,語法糖是啥玩意兒,能吃嗎。。。。。

為了搞清楚這個糖到底是可不可以吃的,我們來一個個搞明白。
以下內(nèi)容參考自知乎的回答
裝飾器
裝飾器本質(zhì)上是一個Python函數(shù),它可以讓其他函數(shù)在不需要做任何代碼變動的前提下增加額外功能,裝飾器的返回值也是一個函數(shù)對象。有了裝飾器,我們就可以抽離出大量與函數(shù)功能本身無關(guān)的雷同代碼并繼續(xù)重用,概括的講,裝飾器的作用就是為已經(jīng)存在的對象添加額外的功能。
先來看一個簡單例子:
def foo():
print('i am foo')
現(xiàn)在有一個新的需求,希望可以記錄下函數(shù)的執(zhí)行日志,于是在代碼中添加日志代碼:
def foo():
print('i am foo')
logging.info("foo is running")
bar()、bar2()也有類似的需求,怎么做?再寫一個logging在bar函數(shù)里?這樣就造成大量雷同的代碼,為了減少重復(fù)寫代碼,我們可以這樣做,重新定義一個函數(shù):專門處理日志 ,日志處理完之后再執(zhí)行真正的業(yè)務(wù)代碼
def use_logging(func):
logging.warn("%s is running" % func.__name__)
func()
def bar():
print('i am bar')
use_logging(bar)
邏輯上不難理解,但是這樣的話,我們每次都要將一個函數(shù)作為參數(shù)傳遞給use_logging函數(shù)。而且這種方式已經(jīng)破壞了原有的代碼邏輯結(jié)構(gòu),之前執(zhí)行業(yè)務(wù)邏輯時,執(zhí)行運行bar(),但是現(xiàn)在不得不改成use_logging(bar)。那么有沒有更好的方式的呢?當(dāng)然有,答案就是裝飾器。
簡單裝飾器
def use_logging(func):
def wrapper(*args, **kwargs):
logging.warn("%s is running" % func.__name__)
return func(*args, **kwargs)
return wrapper
def bar():
print('i am bar')
bar = use_logging(bar)
bar()
函數(shù)use_logging就是裝飾器,它把執(zhí)行真正業(yè)務(wù)方法的func包裹在函數(shù)里面,看起來像bar被use_logging裝飾了。
@符號是裝飾器的語法糖,在定義函數(shù)的時候使用,避免再一次賦值操作(@符號看來是為了減少操作的工作。。。。)
def use_logging(func):
def wrapper(*args, **kwargs):
logging.warn("%s is running" % func.__name__)
return func(*args, **kwargs)
return wrapper
@use_logging
def foo():
print("i am foo")
@use_logging
def bar():
print('i am bar')
bar()
這樣我們就可以省去bar = use_logging(bar)這一句了,直接調(diào)用bar()即可得到想要的結(jié)果。如果我們有其他的類似函數(shù),我們可以繼續(xù)調(diào)用裝飾器來修飾函數(shù),而不用重復(fù)修改函數(shù)或者增加新的封裝。這樣,我們就提高了程序的可重復(fù)利用性,并增加了程序的可讀性。
所以裝飾器是個好東西,要學(xué)會用起來。還有很多關(guān)于裝飾器詳細的解釋,可以看看這個知乎上的回答:https://www.zhihu.com/question/26930016