python 裝飾器基本原理

2021-09-19 09:11:56 字數 3885 閱讀 8139

關於python中裝飾器的定義,我們這裡參考廖雪峰大神的python3教程中的定義:在某個函式(**)執行期間,在不更改該函式的功能下,動態給該函式新增功能的方式,我們稱之為「裝飾器」。從定義中看出,這個裝飾器勢必要在實現中傳入原函式,並在其功能中使原函式功能不受影響。由此我們想到的一種實現裝飾器的方法就是:「實現乙個功能(可是一段**/函式),該功能的實現要傳入乙個函式。」翻譯過來就是通過乙個函式(比如叫「a」函式)實現裝飾器的功能,但是該函式a的入參需要傳入的是乙個函式(比如叫「b」函式)。那麼想象中的裝飾器實現方式是:

# 這裡的b是乙個函式

defa

(b):

b()pass

# 這裡的func是乙個函式,與想象中的b函式一致,log就是上面中的a函式

deflog

(func)

:# *args,**kw泛指函式func的入參

def(

*args,

**kw)

:# __name__是python中的乙個屬性,它能返回對應函式的名稱

print

('call %s():'

% func.__name__)

return func(

*args,

**kw)

要使用裝飾器,python中的方法如下:

# 給函式上面加乙個@符號,再接實現了裝飾器功能的函式名稱

@log

defnow()

:print

('2015-3-25'

)

呼叫now()函式:

>>

> now(

)call now():

2015-3

-25

在python中,「函式也是一種物件」,這句話是理解裝飾器的基礎。因為函式是一種物件,並且物件能被賦值給變數,所以函式就能被賦值給變數。例如:

>>

>

defnow()

:...

print

('2015-3-25').

..>>

> f = now

>>

> f(

)

這裡now函式被賦值給了f變數,呼叫now函式,其實就是進行f的呼叫。平時來看,函式一般都有入參(即函式的區域性變數),而因為變數能代表函式,故函式入參為函式也就好理解了。故對實現了裝飾器的函式,它的入參為函式也就不奇怪了。在python中當乙個函式a就將另乙個函式b作為引數,那麼這個函式a就稱之為高階函式。而上面的函式log將func函式作入參,那麼log就是乙個高階函式。

def

lazy_sum

(*args)

:def

sum():

ax =

0for n in args:

ax = ax + n

return ax

return

sum

函式lazy_sum實現了乙個求和的功能,當我們呼叫lazy_sum時,其返回的不是直接的求和值,而是乙個函式sum,

>>

> f = lazy_sum(1,

3,5,

7,9)

>>

> f

<

locals

>

.sum at 0x101c6ed90

>

這裡f變數其實就是sum函式,所以要求和的值時,呼叫f才可以。

>>

> f(

)25

「當有乙個函式h,它定義了內部函式g,最後返回了函式g,並且在該過程中g還使用了h函式的區域性變數,那麼這種程式python中稱之為閉包」。根據閉包定義,其實它也是一種返回函式,只不過它的內部函式使用了外部函式的區域性變數(入參)。

有了前面的知識儲備,再來看最開始實現了裝飾器功能的函式log:

def

log(func)

:def

(*args,

**kw)

:print

('call %s():'

% func.__name__)

return func(

*args,

**kw)

在python中,當我們使用裝飾器:

@log

defnow()

:print

('2015-3-25'

)now(

)

now()執行過程,實際上相當於執行了語句:

now = log(now)
有時候我們給某個函式動態新增了功能,但又希望我們新增的功能對於我們的需求是可定製的。因此則有必要給裝飾器新增引數變數。python中給裝飾器新增引數的實現是這樣的:

def

log2

(text)

:def

log(func)

:def

(*args,

**kw)

:print

('%s %s():'

%(text, func.__name__)

)return func(

*args,

**kw)

return log

用法則如下:

@log2(

'execute'

)def

now():

print

('2015-3-25'

)

>>

> now(

)execute now():

2015-3

-25

直觀上看,其實就是給log函式外部再加了一層函式。根據前面的函式定義,不難看出log2是乙個返回函式。而now()的執行過程則相當於執行了下面的語句:

now = log2(

'execute'

)(now)

import functools

deflog

(func)

: @functools.wraps(func)

def(

*args,

**kw)

:print

('call %s():'

% func.__name__)

return func(

*args,

**kw)

import functools

deflog2

(text)

:def

log(func)

: @functools.wraps(func)

def(

*args,

**kw)

:print

('%s %s():'

%(text, func.__name__)

)return func(

*args,

**kw)

return log

當然python的裝飾器使用不止這些。這裡只是最基本的理解(若有理解錯的,請各位大佬指正哈)。對裝飾器的理解首先是要知道函式也是物件,其次只要弄清楚一些函式定義就可以了。當然這裡還是得感謝廖雪峰大神的python3教程,正是因為他那清晰透徹的教程,才使我理解裝飾器的概念。

python 裝飾器的基本原理

裝飾器的本質 就是函式,功能是為其他函式新增附加功能 原則 不修改被修飾函式的源 不修改被修飾函式的呼叫方式 import time def cal l start time time.time res 0 for i in l time sleep 0.1 res i stop time time...

mysql的基本原理 Mysql 基本原理

mysql 基本原理 mysql是一種關聯式資料庫管理系統,關聯式資料庫將資料儲存在不同的表中,而不是將所有資料放在乙個大倉庫內,這樣就增加了速度並提高了靈活性 ysql是資料庫登入命令 uroot預設超級使用者登入 p 預設沒密碼 中寫密碼 mysqladmin uroot password 12...

8 2 1 基本原理

乙個舞台動畫物件在包含許多舞台資訊 出現在何處,佔多大面積,處在什麼角度,是否可見 這些資訊分別儲存在動畫物件的屬性中。在 中讀取這些屬性可以了解物件的位置 大小 角度等狀態資訊 修改這些屬性可以改變物件的位置 大小 角度等狀態。如果從資料的角度去理解,動畫就是在固定時間間隔點不斷修改動畫物件某項屬...