Python的裝飾器目养,是一個(gè)Python中一個(gè)比較難以理解的知識(shí)點(diǎn), 今天我試試說(shuō)一說(shuō)毒嫡,說(shuō)的如果不好癌蚁,請(qǐng)見(jiàn)諒。
裝飾器兜畸,從字面意思來(lái)說(shuō)努释,就是修飾一個(gè)事物的,在Python里面的作用就是讓一個(gè)已經(jīng)存在的函數(shù)擁有一個(gè)以前沒(méi)有的功能膳叨。裝飾器本質(zhì)上還是一個(gè)函數(shù)洽洁,知識(shí)他的功能是為其他函數(shù)添加新功能。
那有人會(huì)說(shuō)菲嘴,我在原來(lái)的函數(shù)里面加一些代碼饿自,也可以實(shí)現(xiàn)啊,為什么還要搞個(gè)裝飾器來(lái)增加功能呢龄坪? 當(dāng)然昭雌,如果你給一個(gè)函數(shù)加個(gè)功能,是可以加代碼健田, 但是如果是讓你給100個(gè)函數(shù)代碼塊加一個(gè)相同的功能呢烛卧? 一個(gè)個(gè)改代碼嗎? 你會(huì)奔潰的妓局。
下面說(shuō)說(shuō)一個(gè)裝飾器要實(shí)現(xiàn)总放,要符合一定的規(guī)則,就是兩個(gè)不改動(dòng)
1.不改動(dòng)被裝飾函數(shù)的源代碼
2.不改動(dòng)被修飾函數(shù)的調(diào)用方式
就是你加沒(méi)加這個(gè)裝飾器好爬,函數(shù)要按照原樣來(lái)調(diào)用
下面說(shuō)說(shuō)裝飾器到底怎么寫局雄,怎么用,上面說(shuō)到裝飾器也是一個(gè)函數(shù)存炮,但是這個(gè)函數(shù)和普通的函數(shù)不太一樣炬搭,他是一個(gè)高階函數(shù)蜈漓,那我們給裝飾器大概下個(gè)定義
裝飾器:一個(gè)可以給別的函數(shù)添加新功能的高階函數(shù)(當(dāng)然現(xiàn)在還是不完整的定義)
下面介紹下什么是高階函數(shù)。
高階函數(shù): 一個(gè)可以接受函數(shù)為參數(shù)或者能reture 一個(gè)函數(shù)的函數(shù)就是高階函數(shù)
是不是有點(diǎn)繞宫盔,舉個(gè)例子
def f1():
print('普通函數(shù)')
def f2(func): #f2函數(shù)的參數(shù)是一個(gè)函數(shù)融虽,所以它是一個(gè)高階函數(shù)
print('高階函數(shù)1')
f1()
def f3(func): #f3函數(shù)的返回值是一個(gè)函數(shù),所以它是一個(gè)高階函數(shù)
print('高階函數(shù)2')
return func
f2(f1)
f3(f1)
結(jié)果:
高階函數(shù)1
普通函數(shù)
高階函數(shù)2
有點(diǎn)基礎(chǔ)的人可能知道灼芭,這個(gè)根本就不是裝飾器有额,騙人的。當(dāng)然裝飾器不是這么簡(jiǎn)單姿鸿。
那下面要介紹的一個(gè)東西叫嵌套函數(shù)谆吴,那什么叫嵌套函數(shù)呢? 字面意思應(yīng)該就知道了苛预,函數(shù)里面套一個(gè)子函數(shù)
舉個(gè)例子:
def outer():
print('outer')
def inner():
print('inner')
inner()
outer()
結(jié)果
outer
inner
下面我們要給裝飾器重新下個(gè)定義了句狼。
裝飾器:一個(gè)可以給別的函數(shù)添加新功能的高階函數(shù)+嵌套函數(shù)
那么我們把高階函數(shù)+嵌套函數(shù)結(jié)合在一起看看
一個(gè)可以添加一行日志的裝飾器
def add_log(func): #一個(gè)函數(shù)作為參數(shù),這個(gè)函數(shù)就是我們要
def wrapper():
print('我們要加一些日志') #要給原函數(shù)添加的新功能热某,這里就是打印一行日志腻菇,當(dāng)然可以實(shí)現(xiàn)其他復(fù)雜的功能
func()
return wrapper
#上面可以看到高階函數(shù)+嵌套函數(shù)的影子吧,加一起就是一個(gè)最簡(jiǎn)單的裝飾器拉
@add_log #裝飾器的用法
def f1():
print('普通函數(shù)')
f1() #調(diào)用函數(shù)
結(jié)果:
#看結(jié)果f1里面只有print一行昔馋,但是結(jié)果多了一行筹吐,就是裝飾器的作用
我們要加一些日志
普通函數(shù)
這些裝飾器大概知道上面意思了吧。
下面說(shuō)說(shuō)秘遏,上面的裝飾器丘薛,有沒(méi)有沒(méi)有上面問(wèn)題呢?
看看邦危,仔細(xì)看看洋侨。 看出來(lái)了嗎? 看不出來(lái)倦蚪,我說(shuō)了哦希坚。
上面我們的f1()函數(shù), 沒(méi)有參數(shù)陵且,是不是裁僧,想想如果f1()函數(shù)要加參數(shù)怎么辦啊慕购?
def add_log(func):
def wrapper(name):
print('我們要加一些日志')
func(name)
return wrapper
@add_log
def f1(name):
print('普通函數(shù) %s' %name)
f1('python')
有人是不是想這樣實(shí)現(xiàn)呢聊疲?
當(dāng)然這樣是可以的,但是我們不要忘了裝飾器的作用沪悲,他不是給某一個(gè)固定的函數(shù)來(lái)使用的售睹,假如現(xiàn)在還需要修飾一個(gè)f2(name,age), 那怎么辦啊可训? 沒(méi)辦法昌妹,裝飾器的代碼都給你定死了,所以上面這樣寫是不行的握截。
到底怎么寫呢飞崖?
def add_log(func):
def wrapper(*args,**kwargs):
print('我們要加一些日志')
func(*args,**kwargs)
return wrapper
@add_log
def f1(name):
print('普通函數(shù) %s' %name)
@add_log
def f2(name,age):
print('我是%s,我%s歲了' %(name,age))
f1('python')
f2('java',10)
結(jié)果:
我們要加一些日志
普通函數(shù) python
我們要加一些日志
我是java,我10歲了
上面的寫法,是不是可以了谨胞,是不是固歪,不管任何函數(shù),任何參數(shù)胯努,都OK了牢裳,至于args,*kwargs啥意思,大家可以去百度下啊叶沛。這里就不多說(shuō)了
今天就說(shuō)這么多蒲讯,希望大家對(duì)于python的裝飾器有個(gè)基本的了解。
這里留個(gè)彩蛋灰署,上面的最終的代碼判帮,你覺(jué)得還有問(wèn)題嗎?仔細(xì)看溉箕,如果能看出來(lái)歡迎給我留言晦墙,如何看不出來(lái),看我下回分解肴茄。