摘要:在這種代碼運行期間動態增加功能的方式,稱之為裝飾器。四接收特定類型參數的裝飾器裝飾器可以接收參數,當調用裝飾器返回的函數時,也就調用了包裹函數,把參數傳入包裹函數,它將參數傳遞給被裝飾的函數。執行結果執行結果
【題外話】心塞塞 心情down down down 有段時間沒用裝飾器了,然后然后問著就跪了~~~
回來翻了翻資料和代碼......
裝飾器,decorator,本質上是一個Python函數,它可以讓其他函數在不需要做任何代碼變動的前提下增加額外功能,裝飾器的返回值也是一個函數對象。
裝飾器通過不修改核心代碼而增強核心代碼部分的功能。例如在函數前插入日志、權限校驗、事務處理等場景。
而且可以抽離出大量與函數功能無關的雷同代碼并重用。
Python中函數也可以看做是一個對象,可以賦值給變量,并通過變量調用該函數。
例如:
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()
執行結果:
testfunc Wed Sep 12 15:01:13 2018 foo() called foo1()
說明:執行foo()前,先執行testfunc(foo),再執行wrapper(),返回時調用foo()本身。
四、接收特定類型參數的裝飾器裝飾器可以接收參數,當調用裝飾器返回的函數時,也就調用了包裹函數,把參數傳入包裹函數,它將參數傳遞給被裝飾的函數。
如下:
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五、帶不定參數的裝飾器
當有多個函數需要調用裝飾器,但是函數的參數各不同時,該如何實現呢?總不能一個函數對應一個裝飾器吧。這時候就可以用帶不定參數的裝飾器進行實現。
如下:
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)
運行一下哦~
六、多個裝飾器當一個函數想要加入多項功能時,可以考慮使用多層裝飾器,就是要注意一下裝飾器的執行順序。
舉個栗子:
# 注意代碼的執行順序 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...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/42421.html
摘要:裝飾器傳參被裝飾的函數帶有參數的情況接上一篇,直接上代碼函數也就是被裝飾的函數的運行時間是裝飾器的正確使用,不需要傳參裝飾器的正確使用,需要傳參此時不用再像上面一樣賦值,可以直接調用返回值被裝飾的函數有返回值在裝飾器內部需被裝飾函數的調用 python 裝飾器 傳參 被裝飾的函數帶有參數的情況 接上一篇,直接上代碼 import time def decorator(func): ...
摘要:裝飾器是可調用的對象,其參數是另一個函數被裝飾的函數。第二大特性是,裝飾器在加載模塊時立即執行。另一個常見的裝飾器是,它的作用是協助構建行為良好的裝飾器。 裝飾器是可調用的對象,其參數是另一個函數(被裝飾的函數)。 裝飾器基礎知識 首先看一下這段代碼 def deco(fn): print I am %s! % fn.__name__ @deco def func(): ...
摘要:使用類裝飾器,優點是靈活性大,高內聚,封裝性。不過不用擔心,有,本身也是一個裝飾器,它的作用就是把原函數的元信息拷貝到裝飾器函數中,使得裝飾器函數也有和原函數一樣的元信息。 showImg(https://segmentfault.com/img/bVbrFWb?w=742&h=484);Python的裝飾器(decorator)是一個很棒的機制,也是熟練運用Python的必殺技之一。...
摘要:希望引以為戒鄭傳裝飾模式如果你了解,你肯定聽過裝飾器模式。在面向對象中,裝飾模式指動態地給一個對象添加一些額外的職責。就增加一些功能來說,裝飾模式比生成子類更為靈活。 漫談 如果作為一個Python入門,不了解Python裝飾器也沒什么,但是如果作為一個中級Python開發人員,如果再不對python裝飾器熟稔于心的話,那么可能并沒有量變積累到質變。 我以前也看過很多講python 裝...
摘要:為了避免重復調用,可以適當地做緩存,的裝飾器可以完美的完成這一任務。這意味著我們可以為方法創建裝飾器,只是要記得考慮。裝飾器封裝了函數,這使得調試函數變得困難。另外,使用裝飾器去管理緩存和權限。 原文地址 之前用python簡單寫了一下斐波那契數列的遞歸實現(如下),發現運行速度很慢。 def fib_direct(n): assert n > 0, invalid n ...
閱讀 1220·2021-09-26 09:55
閱讀 3177·2019-08-30 15:55
閱讀 958·2019-08-30 15:53
閱讀 2290·2019-08-30 13:59
閱讀 2374·2019-08-29 13:08
閱讀 1102·2019-08-29 12:19
閱讀 3296·2019-08-26 13:41
閱讀 414·2019-08-26 13:24