python 簡單的裝飾器

2021-10-03 10:32:46 字數 3309 閱讀 6911

今天我們講一講python中的裝飾器。可能初次接觸裝飾器的同學會覺得它很難,其實也就那麼一回事兒,今天就讓我們會會它!

首先它的本質是函式,它的功能是為其他函式新增附加功能

ps:它有兩個原則:

1.不能修改被修飾的函式的**。

2.不能更改被修飾函式的呼叫函式。

我所認為的裝飾器其實就是:

裝飾器 = 高階函式+函式巢狀+閉包

我們先說什麼是高階函式?

當函式(符合其中任意乙個):

函式接收的引數是乙個函式名。

函式的返回值是乙個函式名。

就是把高階函式。

那麼我們考慮當只有高階函式時,我們能否寫出乙個裝飾器?

現在我們只用高階函式實現:執行foo函式時,新增功能:計算其執行時間並列印。試試看吧!

# 裝飾器 = 高階函式 + 函式巢狀 + 閉包

# 先玩玩高階函式

import time

deffoo()

: time.sleep(3)

print

('來自foo'

)def

timer

(func)

: start_time = time.time(

) func(

) stop_time = time.time(

)print

('函式的執行時間是%s'

%(stop_time-start_time)

)timer(foo)

# 改變了函式的呼叫方式

import time

deffoo()

: time.sleep(3)

print

('來自foo'

)def

timer

(func)

: start_time = time.time(

) func(

) stop_time = time.time(

)print

('函式的執行時間是%s'

%(stop_time-start_time)

)return func

foo = timer(foo)

# 沒改變呼叫方式也沒改變函式源**但多執行了一次,不合格

foo(

)# 總結高階函式獨自完不成裝飾器

分析上述兩段**,我們會發現:第一種方式改變了函式的呼叫方式,第二種則多執行了一句**。所以我們總結:高階函式獨自完不成裝飾器!

所以我們需要函式巢狀,和閉包的概念。

#  函式的巢狀與閉包

deffather

(name)

:print

('我是%s'

% name)

defson()

:print

('我的父親是%s'

% name)

defganud()

:print

('我的爺爺是%s'

% name)

ganud(

) son(

)# 閉包先使用自己的作用域。

father(

'liuruochen'

)"""

最後結果是:

我是liuruochen

我的父親是liuruochen

我的爺爺是liuruochen

"""

到這裡大家對高階函式,函式巢狀,閉包應該已經明了。

而裝飾器=高階函式+函式巢狀+閉包。

我們通過一段**來分析。**依舊是指行乙個函式,通過裝飾器給其附加乙個計算執行時間的功能。

# 給test函式新增計算執行時間的附加功能

import time

deftimer

(func)

:# 傳進去test

defwarrp

(*args,

**kwargs)

:# args = (name, age)

# print(args)

start_time = time.time(

) res = func(

*args,

**kwargs)

# 執行test , *args = name, age

stop_time = time.time(

)print

('函式的執行時間是%s'

%(stop_time-start_time)

)return res

return warrp

@ timer # @ timer 就相當於進行了 test = timer(test)

deftest

(age, name)

: time.sleep(3)

print

('【%s】年齡大的【%s】函式執行完畢!'

%(age, name)

)return

'這是fan'

# test = timer(test) # 這裡拿到的是warrp的位址,當沒有@timer時必須多謝這句**。

res = test(18,

'liu'

)# 實際上執行的是warrp

print

(res)

"""結果:

年齡大的【liu】函式執行完畢!

函式的執行時間是3.0004591941833496

這是fan

"""

注:

給大家分析一下它的過程。

首先,匯入time模組,定義test函式,timer函式(我說過裝飾器本質就是乙個函式)

我們主要分析這個timer函式,大家可以看到,它的傳參是乙個函式名,返回值也是乙個函式名。那麼:timer(test)得到的是warrp函式的位址。我們進行test = timer(test)之後,這時的test其實變成了warrp函式。然後我們再進行test(18,「liu」)實際上就是進行warrp(18,liu)

(這裡注意warrp引數的問題 args **kwargs 這裡不做解釋,如果需要文末會有一些部落格解釋它們。)。之後在函式warr()中執行了test()函式。

:解釋arg **kwarg問題。

python簡單裝飾器 python裝飾器簡單使用

理解裝飾前先理解python閉包的概念 下面是對裝飾器的簡單舉例 實質 是乙個函式 引數 是你要裝飾的函式名 並非函式呼叫 返回 是裝飾完的函式名 inner 作用 為已經存在的物件新增額外的功能 特點 不需要對物件做任何的 上的變動 被裝飾的函式無引數 def decorate func 裝飾器列...

簡單易懂的python裝飾器

利用高階函式和閉包,實現不改變已實現的功能和呼叫方式的情況下增加功能 def log func def inner args,kw print call s func.name return func args,kw return inner log def now print 2015 3 25 ...

python裝飾器的簡單實用

裝飾器 decorators 可以實現在不變原有python 功能的基礎上增加功能 框架def outer2 func def inner args,kwargs func args,kwargs return inner outer2 def foo a,b,c print a b c 示例一 i...