Python裝飾器的原理與應用

2022-08-28 16:33:19 字數 4337 閱讀 8678

裝飾器是什麼東西呢?就是起到裝飾作用的這麼乙個函式,那這玩意有啥用呢?很多人都會丟擲這樣的疑問,咱們就通俗的說一下這個裝飾器到底是什麼東西,是什麼工作原理呢?

首先,裝飾顧名思義就是裝飾用,為什麼需要對函式裝飾呢?是因為要遵循乙個「開放」--「封閉」原則,因為已經寫好的函式可能已經經過很久的測試和應用,沒有出現任何問題的函式體,如果對函式內部進行修改勢必會造成一些意外的問題,另外,這個函式很有可能不是你自己寫的,那麼對函式內部結構不熟悉,變數的不熟悉等等也可能導致函式的執行出現問題。那麼裝飾器就起到了不改變原函式的功能和不改動原函式內部**的前提下,給函式新增功能的作用。

就如同乙個麵包,想要增加奶油或果糖,如果拋開麵包加入到麵包中,不單單影響美觀,還破壞了麵包本身。那麼在麵包外層塗上忌廉或果糖等等,不僅能達到想要的效果,還不會破壞麵包本身。。這就是裝飾器。

裝飾器的基本形式

一般情況下,我們可以在要增加功能的函式前加上另外乙個函式,來達到目的。

例如:

1

deffunc_new():

2print('

這裡是func_new函式的輸出。')

3 func() #

在函式內部呼叫原函式

4print('

呼叫完畢')

56deffunc():

7print('

這裡是原函func數的輸出')

89func_new()

#輸出結果:

>>>這裡是func_new函式的輸出。

>>>這裡是原函func數的輸出

>>>呼叫完畢

雖然起到了裝飾作用,也沒有改變原函式內部,但我們在呼叫的時候卻改變了呼叫的函式名。這在日常工作中是不可以的,因為原來的函式可能被很多部門或很多程式呼叫,那麼如果為了增加函式的功能卻改變其他程式或部門的呼叫那簡直就是災難。

如何讓函式的呼叫依舊是原來的呼叫方式不改變,然後對這個函式增加功能呢?

讓我們在執行原函式前執行其他函式,並且在函式沒有被呼叫時不執行其他函式的呼叫。

如果:func = funcnew(func) 看似可以使用func()來呼叫原函式,但是,funcnew(func)在賦值給func變數之前就已經被執行了。這樣是不對的。那麼如何讓func_new(func)賦值前不執行呢? 這裡就用到了巢狀函式

def

func_new(func):

def inner(): #

巢狀乙個函式inner

print('

這裡是func_new函式的輸出。')

func()

#在函式內部呼叫原函式

print('

呼叫完畢')

return inner #

返回inner的記憶體位址。 (不要加括號哦,加了括號就是執行了。失去這個巢狀函式的意義了.)

這樣做乙個巢狀,那麼當 func = funcnew(func) 時 funcnew(func) 不會被執行,而是返回了乙個函式記憶體位址,這是因為func_new雖然被執行了。但返回的是inner,而inner沒有被執行而返回的是inner的記憶體位址,所以,func得到的是乙個函式記憶體位址。

func = func_new(func)   #

這時變數func得到的是記憶體位址,func_new()函式沒有執行。

func() #

與原函式名一致,執行後是修飾過的結果。

這時,函式裝飾器的原理就搞定了。那麼說,如果每次給函式新增裝飾器都要做賦值操作,這樣太麻煩了。。。是的,python呼叫裝飾器時用@。使用裝飾器時,在要裝飾的函式上方,加上@裝飾器函式名。------看**。

@func_new    #

呼叫裝飾器函式

deffunc():

print('

這裡是原函func數的輸出')

func()

#執行函式,功能實現。

是不是明白了一些呢?讓我們把裝飾器基本型列出來,從頭再來看一下。。

裝飾器基本型: 

def decorator(): #

這裡是裝飾器引數,裝飾器也可以帶入引數,函式呼叫裝飾器時如果是帶有引數的裝飾器需要@decorator(引數)

def outer(func): #

這裡的func是需要裝飾的函式名,使用@呼叫裝飾器時,函式名會被自動帶入。

def inner(*args,**kwargs): #

非固定引數是被呼叫函式的引數。

'''這裡是需要

裝飾的內容

'''return func(*args,**kwargs) #

在裝飾內容執行完畢後,執行原函式。

return

inner

return outer

讓我們引用乙個簡單的小例項來看看裝飾器如何使用。

1

#這是乙個記錄程式執行時間的小程式,用裝飾器來對執行進行認證,並由裝飾器來記錄每個函式執後所需的時間。

2import

time

34 pwd = '

123'

5 swith =false

6def login(func): #

實現認證執行的裝飾器

7def inner(*args,**kwargs): #

為了能使函式呼叫到引數,不管套用了多少層的裝飾器,都需要加入非固定引數

8global

swith9if

notswith:

10 n = input('

>>>')

11if n ==pwd:

12 swith =true

13return func(*args,**kwargs)

14else:15

return

16else:17

return func(*args,**kwargs)

18return

inner

1920

21def sum_t(func): #

記錄程式執行時間的裝飾器

22def inner(*args,**kwargs): #

接受函式的引數

23 start =time.time()

24 f = func(*args,**kwargs)

25 end =time.time()

26print(end -start)

27return f #

返回函式返回值

28return inner #

裝飾器中的功能一定要包含呼叫裝飾器函式的所有功能。否則得不到正確返回值或出錯!

2930

#三種不同形式的函式

31 @login #

先呼叫 認證裝飾器,認證通過後執行函式功能。

32 @sum_t #

通過認證後,呼叫時間記錄裝飾器

33def f1(): #

不帶引數和返回值的函式

34 time.sleep(2)

35print('f1'

)3637@login

38@sum_t

39def f2(a): #

帶引數的函式。

40 time.sleep(2)

41print('f2'

,a)42

43@login

44@sum_t

45def f3(): #

帶return 返回值的函式

46 time.sleep(2)

47print('f3'

)48return'結束

'#函式中,如果有返回值在裝飾器中也需要相應的加入對應的返回項

4950

if__name__ == '

__main__':

51f1()

52 f2('ok'

)53 f =f3()

54print(f)

#

執行結果:

>>>123 #

輸入密碼通過後,依次執行。

f12.0004823207855225f2 'ok'

2.0012047290802f3

2.000471353530884

'結束'

PYTHON 裝飾器 的應用原理

今天回顧了一下裝飾器知識,來記錄一下個人的體悟.看了幾個大神的部落格,對裝飾器的解釋如下 假設我們要增強函式的功能,比如,在函式呼叫前後自動列印,但又不希望修改函式的定義,這種在 執行期間動態增加功能的方式,稱之為 裝飾器 decorator 我個人覺得說的太籠統,因為我下面的 完成了上述的要求卻不...

python裝飾器原理 Python裝飾器原理

裝飾器 decorator 是物件導向設計模式的一種,這種模式的核心思想是在不改變原來核心業務邏輯 的情況下,對函式或類物件進行額外的修飾。python中的裝飾器由python直譯器直接支援,其定義形式如下 decorator def core service 要理解上述 的含義,我們從自定義函式裝...

python 裝飾器應用

裝飾器應用 裝飾器的主要作用是 列印日誌,檢測效能,資料庫事物,url路由 應用1,生成標籤 def bold fn def 閉包,這個函式的作用就是給原來的函式增加一些功能,return fn bold deftest return python in 2 test out 2 python 等價...