最近看了一點(diǎn)點(diǎn)scrapy代碼,其實(shí)完全沒看明白。這代碼中常常會出現(xiàn)@符號標(biāo)記的函數(shù),其實(shí)這就是裝飾器。裝飾器能給函數(shù)提供額外的功能。
def f(x):
return x*x
上面的函數(shù)是一個普通的小函數(shù),但是要是我想在函數(shù)中打印x的參數(shù)值,看樣子我得該一下f的代碼。還有我要限定x只能是數(shù)值類型,那么我也得修改一下代碼。針對各式各樣附加的需求,顯然改代碼是不合適的,我不能每要一個功能就在核心模塊進(jìn)行修改。
def f1(func):
def nf(x):
print(x)
return func(x)
return nf
ff = f1(f)
上面的代碼滿足我們的要求,但是不夠漂亮??梢栽囋囇b飾器,看下面的代碼多簡單。
@f1
def f(x):
return x*x
如果要檢查類型怎么辦?
def type_check(func):
def nf(x):
if isinstance(x,int):
return func(x)
else:
print('type error')
return nf
上面的方法也能實(shí)現(xiàn)我們的需求,但是這有個問題,這個函數(shù)只能做一種類型檢查就是int,那我要是檢查別的類型怎么辦,看樣子裝飾器需要帶參數(shù)才行。
def type_check(target_type):
def f(func):
def nf(x):
if isinstance(x,target_type):
return func(x)
else:
print('type error')
return nf
return f
仔細(xì)關(guān)注上面的代碼,這個可與上面的差別有點(diǎn)大?
這函數(shù)內(nèi)f其實(shí)才是裝飾器,也不知道我這么理解對不對,當(dāng)一個裝飾器帶參數(shù)的時候,也就是意味著要運(yùn)行一次返回一個函數(shù),這個函數(shù)才是真正的裝飾器。
上面的裝飾器只對應(yīng)函數(shù)只有一個參數(shù)的形式,要做到通用這里可以使用如下代碼:
def logging(func):
def wrapper(*args, **kwargs):
print("%s is running" % func.__name__)
return func(*args,**kwargs)
return wrapper