【題外話】心塞塞 \ 心情down down down \ 有段時間沒用裝飾器了,而後而後問着就跪了~~~
回來翻了翻資料和代碼......app
裝飾器,decorator,本質上是一個Python函數,它可讓其餘函數在不須要作任何代碼變更的前提下增長額外功能,裝飾器的返回值也是一個函數對象。
裝飾器經過不修改核心代碼而加強核心代碼部分的功能。例如在函數前插入日誌、權限校驗、事務處理等場景。
並且能夠抽離出大量與函數功能無關的雷同代碼並重用。函數
例如:this
def foo(): print("2017-06-08") f = foo # 將函數賦值給變量,f爲函數對象 f() # 返回結果: 2017-06-08
假設如今要加強foo()的功能,例如,在函數調用前打印日誌。可是又不但願修改foo()函數的定義。在這種代碼運行期間動態增長功能的方式,稱之爲「裝飾器」。
以下:日誌
def testfunc(func): print('testfunc') def wrapper(): print("%s %s() called" %(time.ctime(),func.__name__)) return func() return wrapper @testfunc def foo(): print('foo1()') foo() # 至關於執行testfunc(foo) ->wrapper(foo) -> foo()
執行結果:code
testfunc Wed Sep 12 15:01:13 2018 foo() called foo1()
說明:執行foo()前,先執行testfunc(foo),再執行wrapper(),返回時調用foo()自己。orm
以下:對象
def testfunc_with_args(func): def wrapper_argus(arg1, arg2): print("I got args! Look:", arg1, arg2) func(arg1, arg2) return wrapper_argus @testfunc_with_args def full_name(first_name, last_name): # 帶參數,將參數傳給被裝飾的函數 print("My name is", first_name, last_name) full_name("Peter", "Venkman") # 調用
執行結果:事務
I got args! Look: Peter Venkman My name is Peter Venkman
當有多個函數須要調用裝飾器,可是函數的參數各不一樣時,該如何實現呢?總不能一個函數對應一個裝飾器吧。這時候就能夠用帶不定參數的裝飾器進行實現。
以下:it
def log(func): def wrapper(*args,**kwargs): # 可接受各類參數 print('call %s():'% func.__name__) return func(*args,**kwargs) # 返回一個函數 return wrapper # 裝飾器返回一個函數,進入到wrapper() @log # @log放到now()的定義處,至關於執行語句:now = log(now) def now_1(a,b): print('now()1:a+b = ',a+b) @log def now_2(a,b,c): print('now_2():a+b+c = ',a+b+c) now_1(1,2) now_2(1,2,3)
運行一下哦~io
當一個函數想要加入多項功能時,能夠考慮使用多層裝飾器,就是要注意一下裝飾器的執行順序。
舉個栗子:
# 注意代碼的執行順序 def deco_1(func): print('------111111------') def wrapper(*args,**kwargs): # 包裹函數,參數與原函數的參數一致 print('start: this is deco_1.') func(*args,**kwargs) print('end: deco_1.') return wrapper # 返回值是一個包裹函數 def deco_2(func): print('------222222------') def wrapper(*args,**kwargs): print('start: this is deco_2.') func(*args,**kwargs) print('end: deco_2.') return wrapper @deco_1 @deco_2 def now_1(a,b): print('now()1:a+b = ',a+b) now_1(1,2)
運行結果:
# 結果,注意執行順序: ------222222------ ------111111------ start: this is deco_1. start: this is deco_2. now()1:a+b = 3 end: deco_2. end: deco_1.
除了給被裝飾的函數帶參數,裝飾器自己也能夠帶參數。
def logging(level): def wrapper(func): def inner_wrapper(*args, **kwargs): print("[{level}]: enter function {func}()".format(level=level, func=func.__name__)) return func(*args, **kwargs) return inner_wrapper return wrapper @logging(level='INFO') def say(something): print("say {}!".format(something)) @logging(level='DEBUG') def do(something): print("do {}...".format(something)) say('hello') do("my work")
執行結果:
# 執行結果: [INFO]: enter function say() say hello! [DEBUG]: enter function do() do my work...
❤ thanks for watching, keep on updating...