1. 程式人生 > 其它 >DFS尋找有向圖環的迴圈節點和多路徑到達節點(CF1547G)

DFS尋找有向圖環的迴圈節點和多路徑到達節點(CF1547G)

簡單例子理解裝飾器的作用

裝飾器的作用就是:用一個新函式封裝舊函式(是舊函式程式碼不變的情況下增加功能)然後會返回一個新函式,新函式就叫做裝飾器,一般為了簡化裝飾器會用語法糖@新函式來簡化

例子:

這是一段程式碼,但功能太少,要對這個進行增強,但又不能改變程式碼。

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)