DFS尋找有向圖環的迴圈節點和多路徑到達節點(CF1547G)
阿新 • • 發佈:2021-07-13
簡單例子理解裝飾器的作用
裝飾器的作用就是:用一個新函式封裝舊函式(是舊函式程式碼不變的情況下增加功能)然後會返回一個新函式,新函式就叫做裝飾器,一般為了簡化裝飾器會用語法糖@新函式
來簡化
例子:
這是一段程式碼,但功能太少,要對這個進行增強,但又不能改變程式碼。
def hello():
return "hello world!"
現在我們的需求是要增強hello()
函式的功能,希望給返回加上HTML標籤,比如hello world,但要求我們不得改變hello()
函式原來的定義。
def make_italic(fun): #makitalic傳了一個新函式 def wrapped(): return "<i>"+fun()+"</i>" #要加入的新功能 return wrapped #返回的是wrapped函式功能 def hello(): #對這個功能進行增強 return "hello world!" #make_italic裡面傳入了hello函式,然後內部函式fun()函式也就相當於hello函數了 hello_2=make_italic(hello) #列印新函式,返回的就是<i>hello world!</i> print(hello_2())
為了增強原函式hello
的功能,定義了一個函式,它接收原函式作為引數,並返回一個新的函式,在這個返回的函式中,執行了原函式,並對原函式的功能進行了增強。
事實上,make_italic
就是一個裝飾器(decorator
),它封裝了原函式hello
,並返回了一個新函式,用於增強原函式的功能,並將其賦值給hello。
一般情況下,我們使用裝飾器提供的@語法糖(Syntactic Sugar
),來簡化上面的操作。
#使用@語法糖 def make_italic(fun): def wrapped(): return "<i>" + fun() + "</i>" return wrapped @make_italic #使用了裝飾器可以直接呼叫,不需要賦值了 def hello(): return "hello world" print(hello()) #使用了裝飾器可以直接呼叫,不需要賦值了
像上面的情況,可以動態的修改函式(或類的)功能的函式就是裝飾器。本質上,它是一個高階函式,以被裝飾的函式(比如上面的hello
)為引數,並返回一個包裝後的函式(比如上面的wrapped
)給被修飾函式(hello
)。
當呼叫hello()函式時,hello函式的執行流程如下分析:
1.把hello
函式作為引數傳給@符號後面的裝飾器函式。
2.然後開始執行裝飾器函式,並返回一個包裝了的函式,同時,改變原函式的指向,現在原函式指向了這個包裝函式。
3.執行原函式,其實此時執行的是包裝了的函式,所以說,裝飾器增強了一個現有函式的功能,但不會改變現有函式的定義。
普通裝飾器的使用形式:
@decorator def fun(): pass #格式就如同下面的: def fun(): pass fun = decorator(fun)#不使用語法糖要進行賦值
裝飾器可以定義多個,離函式定義最近的裝飾器最先被呼叫,比如:
@decotator_one
@decorator_two
def fun():
pass
#格式如同下面的:
def fun():
pass
fun = decorator_one(decorator_two(fun))
裝飾器還可以帶引數,比如:
@decorator(arg1, arg2)
def fun():
pass
#格式如同下面的:
def fun():
pass
fun = decorator(arg1, arg2)(fun)