python裝飾器就是用于擴(kuò)展原函數(shù)功能的一種函數(shù),這個(gè)函數(shù)特殊的地方就是它的返回值也是一個(gè)函數(shù),使用Python裝飾器的一個(gè)好處就是:在不需要修改原函數(shù)代碼的情況下,給函數(shù)增加新的功能。
先來(lái)看個(gè)例子:
def say():
print('Nice day')
say()
# 這個(gè)函數(shù)的輸出為:
Nice day
現(xiàn)在,我想在輸出Nice day
的前面再打印一行****************
,類(lèi)似下面的效果:
****************
Nice day
一般情況下,我可以修改上面的代碼:
def say():
print('****************')
print('Nice day')
say()
可是,如果我忽然發(fā)現(xiàn)自己看錯(cuò)了需求,這時(shí)候又要把代碼修改到原來(lái)的樣子,慶幸的是我只是在原來(lái)函數(shù)的基礎(chǔ)上增加了一行代碼,想要回到原來(lái)的狀態(tài)并不難,可如果我是修改了復(fù)雜的邏輯,代碼有一百行呢,難道我還要一步步撤銷(xiāo)嗎?顯然做不到,不過(guò)沒(méi)關(guān)系,肯定還有別的辦法:
def say():
print('Nice day')
def outer(): # 重新定義一個(gè)新函數(shù)
print('****************') # 處理新的邏輯
say() # 再調(diào)用原來(lái)的函數(shù)
outer()
# 現(xiàn)在的輸出為:
'''
****************
Nice day
'''
怎么樣,看上去已經(jīng)滿足要求了吧,不過(guò)仔細(xì)一看,就能發(fā)現(xiàn)新的問(wèn)題,如果不僅僅是say()
函數(shù)需要打印****************
,新來(lái)的talk()
函數(shù)也需要呢,這時(shí)候我又要再寫(xiě)一個(gè)outer()
函數(shù)嗎?這會(huì)累壞丹丹的,所以得再想個(gè)辦法:
def say():
print('Nice day')
def talk():
print('I am talk')
def outer(func): # 接收一個(gè)函數(shù)
print('****************') # 處理新的邏輯
func() # 調(diào)用傳遞過(guò)來(lái)的函數(shù)
outer(talk) # 把talk函數(shù)作為參數(shù)傳遞過(guò)去
# 輸出結(jié)果如下:
'''
****************
I am talk
'''
這時(shí),不管有幾個(gè)函數(shù)需要打印****************
,我直接把函數(shù)名傳給outer()
就可以啦,是不是方便很多^-^ 但是勤勞的丹丹會(huì)止步于此嗎?肯定不會(huì),于是又把代碼做了如下修改:
def say():
print('Nice day')
def outer(func):
def inner():
print('****************')
func() # 相當(dāng)于 say()
return inner
s = outer(say) # 相當(dāng)于 s = inner
s() # 相當(dāng)于 inner()
猜猜這次的是輸出是什么~當(dāng)然還是和上面一樣啦!其實(shí)這里只是把處理邏輯的部分封裝在了一個(gè)函數(shù)里面,調(diào)用outer(say)
的時(shí)候,把say
傳給outer
,獲得返回值inner
給s
,此時(shí)的s
就相當(dāng)于inner
,s()
也就相當(dāng)于inner()
,所以會(huì)輸出:
**************
Nice day
這就是一個(gè)最簡(jiǎn)單的裝飾器啦,是不是很簡(jiǎn)單~ 但是我們每次在使用的時(shí)候還需要先賦值給一個(gè)變量(這里的s),然后再經(jīng)由s調(diào)用,未免違反了丹丹“多一行代碼都是累贅”的原則,所以我們?cè)傩薷囊幌麓a:
def outer(func):
def inner():
print('****************')
func()
return inner
@outer # 用outer裝飾say
def say():
print('Nice day')
say() # 調(diào)用say函數(shù)
我把outer
和say
調(diào)換了一下位置,先定義了outer
函數(shù),@outer
表示用outer
裝飾say
,這樣直接用say()
就能實(shí)現(xiàn)我想先打印一行****************
的功能了,如果不調(diào)換兩個(gè)函數(shù)的位置,是會(huì)報(bào)NameError: name 'outer' is not defined
的錯(cuò)誤的噢(作用域的原因,outer
未定義),這個(gè)應(yīng)該算是復(fù)雜一點(diǎn)的裝飾器了吧,哈哈
這時(shí)候很多細(xì)心同學(xué)肯定就會(huì)問(wèn)了,你寫(xiě)的都是無(wú)參的呀,那如果我的函數(shù)有參數(shù)怎么辦呢,參數(shù)還是不固定的又該怎么辦呢?萬(wàn)能的python+聰明的丹丹當(dāng)然可以解決:
# 帶參數(shù)的裝飾器
def outer(func):
def inner(name):
func(name)
return inner
@outer
def say(name):
print('name is %s.' % (name))
say('dandan')
# name is dandan.
不過(guò)這個(gè)參數(shù)個(gè)數(shù)是固定的,萬(wàn)一我又突發(fā)奇想,想多傳一個(gè)hobby
或者age
怎么辦呢?
# 帶不定參數(shù)的裝飾器
def outer(func):
def inner(*args, **kwargs):
func(*args, **kwargs)
return inner
@outer
def say(name, age):
print('name is %s, age is %d.' % (name, age))
@outer
def talk(name, age, hobby):
print('name is %s, age is %d, hobby is %s.' % (name, age, hobby))
say('dandan', 18)
talk('dandan', 18, 'Coding')
'''
name is dandan, age is 18.
name is dandan, age is 18, hobby is Coding.
'''
如果我要新增的功能有很多,一個(gè)裝飾器搞不定,怎么辦呢?我可以同時(shí)使用多個(gè)裝飾器嗎?當(dāng)然可以:
# 多個(gè)裝飾器
def outer(func):
def inner(*args, **kwargs):
print('****************')
func(*args, **kwargs)
return inner
def outer2(func):
def inner2(*args, **kwargs):
print('這里有1w+新功能')
func(*args, **kwargs)
return inner2
@outer
@outer2
def say(name, age):
print('name is %s, age is %d.' % (name, age))
@outer
@outer2
def talk(name, age, hobby):
print('name is %s, age is %d, hobby is %s.' % (name, age, hobby))
say('dandan', 18)
talk('dandan', 18, 'Coding')
'''
****************
這里有1w+新功能
name is dandan, age is 18.
****************
這里有1w+新功能
name is dandan, age is 18, hobby is Coding.
'''
要注意的是,多個(gè)裝飾器的執(zhí)行順序是從第一個(gè)裝飾器開(kāi)始,執(zhí)行到最后一個(gè)裝飾器,再執(zhí)行函數(shù)本身。
到此這篇關(guān)于python裝飾器代碼深入講解的文章就介紹到這了,更多相關(guān)python裝飾器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- 如何正確理解python裝飾器
- Python必備基礎(chǔ)之閉包和裝飾器知識(shí)總結(jié)
- python 裝飾器的使用與要點(diǎn)
- Python pytest裝飾器總結(jié)(實(shí)例詳解)
- Python 的lru_cache裝飾器使用簡(jiǎn)介
- python 裝飾器重要在哪
- Python 中的函數(shù)裝飾器和閉包詳解
- 詳解Python模塊化編程與裝飾器
- python 裝飾器的基本使用
- Python高階函數(shù)與裝飾器函數(shù)的深入講解
- python中的裝飾器該如何使用