python裝飾器很是的強大,裝飾器能夠在不修改原代碼的狀況下,爲函數添加新的功能,這也適應了開發的模式。要了解裝飾器,首先要明白函數的調用方式。咱們知道函數名就是函數的地址,地址+()就是調用這個函數。python
1.函數的調用ide
函數名+()就是調用這個函數函數
def food(): print("food") food#不會調用,food是food函數的地址 food()#調用
2.函數做爲參數ui
既然函數名是一個地址,那麼咱們可不能夠把這個地址做爲參數傳進另一個函數再調用呢code
def food(func):#給food函數增長一個形參 print("food") func()#在此處調用func即傳進來的fruit函數 def fruit(): print("fruit") food(fruit)#把函數名傳進另外一個函數
那麼這和裝飾器有什麼關係?裝飾器就是利用函數即變量這一律念,把要裝飾的函數傳進另一個函數進行調用,而且在另外的函數上再添加新的功能。開發
3.簡單的裝飾器it
def decorator(func): def inside(): func()#在內部調用傳進來的函數 print("inside")#新的功能 return inside#返回的是函數地址 def food(): print("food") food=decorator(food)#把food傳進去,返回的地址賦值給food,函數即變量,能夠賦值給一個變量 food()#調用返回的函數
在decorator函數嵌套一個函數inside,在inside中調用傳進來的函數,可是咱們不直接調用,而是返回了inside的地址,在外面定義一個變量接收他的地址,而後調用。這就是裝飾器,food()已經不是原來的food函數了,是一個通過decorator裝飾的函數。在python中,裝飾器有本身的寫法,就是用@+函數名class
def decorator(func): def inside(): func()#在內部調用傳進來的函數 print("inside")#新的功能 return inside#返回的是函數地址 @decorator#等價於food=decorator(food) def food(): print("food") food()#調用返回的函數
那麼若是被修飾的函數帶有參數怎麼辦?變量
4.被修飾的函數帶有參數裝飾器
當被修飾的函數帶有參數,那麼這個參數會傳給inside函數,而且能夠調用這些參數
def decorator(func): def inside(a,b):#再這裏接收被修飾函數的參數 func(a,b)#在內部調用傳進來的函數 print("sum=",a+b)#內部調用傳進來的參數 print("inside")#新的功能 return inside#返回的是函數地址 def food(a,b): print("food") food(1,2)#調用返回的函數
若是裝飾函數和被裝飾函數都帶有參數怎麼辦?
5.裝飾函數帶有參數
裝飾函數帶有參數時,被修飾函數就不能再傳給最外層函數了,但能夠往裏面一層傳,也就是能夠在裝飾函數再繼續嵌套函數。
def decorator(dec1,dec2):#decorator本身的參數 def outside(func):#被修飾的函數 def inside(a,b):#被修飾函數的參數 func()#調用 print("sum=",a+b)#使用被修飾函數的參數 print("from decorator:",dec1+dec2)#decorator自己的參數 return inside#返回地址 return outside#返回 @decorator(1,2)#decorator的參數 def food(a,b): print("food") food()#food函數的調用方式沒有改變
6.一個函數被多個裝飾器修飾
一個函數是能夠被多個裝飾器裝飾的,只需在函數名上加上@+函數名
def decorator1(func): def inside(): func() print("from decorator1") return inside def decorator2(func): def inside(): func() print("from decorator2") return inside #多個裝飾器,等價於food=decorator2(decorator1(food)) @decorator2 @decorator1 def food(): print("from food") food()#正常調用