在軟體開發過程中,不同的階段設計開發時會定義一些函式,而後期的開發過程中,希望擴充套件一些裝飾這個函式的內容,即裝飾器;舉例如下
存在乙個計算兩個數相加的函式
def
add(a , b)
:'''
求任意兩個數的和
'''r = a + b
return r
res = add(
123,
456)
print
(res)
執行結果:
579
希望在執行這個計算前程式輸出"計算開始…";計算時輸出"計算結束…" 前提是不能改變原函式;如下所示
#定義乙個函式,達到需求的設計
defnew_add
(a,b)
:print
('計算開始~~~'
) r = add(a,b)
print
('計算結束~~~'
)return r
r = new_add(
111,
456)
print
(r)執行結果
計算開始~~~
計算結束~~~
567
以上的設計雖然完成了需求,但是相對應的也帶來了一些問題
為了解決這個問題,建立乙個可以自動的生產函式
# 用於計算兩個數相加
defadd
(a,b)
: r = a+b
return r
# 用於計算兩個數相乘
defmul
(a,b)
: r = a*b
return r
defdecorators
(fun)
:'''
這是乙個裝飾器函式
用來對其他函式進行擴充套件,使其他函式可以在執行前列印開始執行,執行後列印執行結束
引數:fun 要擴充套件的函式物件
'''# 建立乙個新函式
''' *args 用於接收所有的位置引數
**kwargs 用於接受所有的關鍵字引數
'''defnew_fun
(*args,
**kwargs)
:#將引數裝包成元組或字典
print
('計算開始...'
)# 呼叫被擴充套件的函式
num = fun(
*args,
**kwargs)
#將元組拆包成位置引數,將字典拆包成關鍵字引數
print
('計算結束...'
)# 返回函式的執行結果
return num
# 返回新函式
return new_fun
# 呼叫
r = decorators(add)
# 將裝飾器函式的返回值函式,即內部的函式給到r
print
(r)# r就是裝飾器函式的內部函式的記憶體位址
res = r(
123,
456)
# 向內部函式傳參,相當於add(123,456)
print
(res)
執行結果
<
locals
>
.new_fun at 0x0000016afffb6950
>
計算開始...
計算結束...
579
計算兩個數相乘的情況,如下呼叫
r = decorators(add)
print
(r)res = r(
123,
456)
print
(res)
print
('-'*30
)r = decorators(mul)
print
(r)res = r(2,
3)print
(res)
執行結果
<
locals
>
.new_fun at 0x000001d00b7168c8
>
計算開始...
計算結束...
579---
----
----
----
----
----
----
---<
locals
>
.new_fun at 0x000001d00b716950
>
計算開始...
計算結束...
6
可見,每次呼叫裝飾器函式的內部函式時,分配的記憶體肯定是不一樣的,傳入的add、mul實參
就是真實計算的函式內容
如下所示:函式裝飾器的內容不變,只是在定義函式的時候加上@裝飾器函式的名稱
即可
但是這樣一來,裝飾器就與函式實體進行了繫結,以後呼叫函式時都會攜帶裝飾器
def
decorators
(fun)
:'''
這是乙個裝飾器
用來對其他函式進行擴充套件,使其他函式可以在執行前列印開始執行,執行後列印執行結束
引數:fun 要擴充套件的函式物件
'''# 建立乙個新函式
''' *args 用於接收所有的位置引數
**kwargs 用於接受所有的關鍵字引數
'''defnew_fun
(*args,
**kwargs)
:#將引數裝包成元組或字典
print
('計算開始...'
)# 呼叫被擴充套件的函式
num = fun(
*args,
**kwargs)
#將元組拆包成位置引數,將字典拆包成關鍵字引數
print
('計算結束...'
)# 返回函式的執行結果
return num
# 返回新函式
return new_fun
# 對函式實體進行裝飾
@decorators
defadd
(a,b)
: r = a+b
return r
@decorators
defmul
(a,b)
: r = a*b
return r
# 呼叫
res = add(
123,
456)
print
(res)
print
('-'*30
)res = r(2,
3)print
(res)
計算開始...
計算結束...
579---
----
----
----
----
----
----
---計算開始...
計算結束...
6
def
fn1(fun)
:def
new_function
(*args ,
**kwargs)
:print
('fn1裝飾~開始執行~~~~'
) result = fun(
*args ,
**kwargs)
print
('fn1裝飾~執行結束~~~~'
)return result
return new_function
deffn2
(fun)
:def
new_function
(*args ,
**kwargs)
:print
('fn2裝飾~開始執行~~~~'
) result = fun(
*args ,
**kwargs)
print
('fn2裝飾~執行結束~~~~'
)return result
return new_function
@fn1
@fn2
defsay_hello()
:print()
say_hello(
)
由內到外的執行就是,以say_hello()函式的輸出結果為中心,先使用fn2裝飾器,然後使用fn1裝飾器
執行結果
fn1裝飾~開始執行~~~
~fn2裝飾~開始執行~~~
~~~fn2裝飾~執行結束~~~
~fn1裝飾~執行結束~~~
~
改變順序
@fn2
@fn2
defsay_hello()
:print()
say_hello(
)執行結果
fn2裝飾~開始執行~~~
~fn1裝飾~開始執行~~~
~~~fn1裝飾~執行結束~~~
~fn2裝飾~執行結束~~~
~
python裝飾器 Python 裝飾器
簡言之,python裝飾器就是用於拓展原來函式功能的一種函式,這個函式的特殊之處在於它的返回值也是乙個函式,使用python裝飾器的好處就是在不用更改原函式的 前提下給函式增加新的功能。一般而言,我們要想拓展原來函式 最直接的辦法就是侵入 裡面修改,例如 這是我們最原始的的乙個函式,然後我們試圖記錄...
python裝飾器 裝飾器
由於函式也是乙個物件,而且函式物件可以被賦值給變數,所以,通過變數也能呼叫該函式。def now print 2015 3 25 f now f 2015 3 25 函式物件有乙個 name 屬性,可以拿到函式的名字 now.name now f.name now 現在,假設我們要增強now 函式的...
python裝飾器原理 Python裝飾器原理
裝飾器 decorator 是物件導向設計模式的一種,這種模式的核心思想是在不改變原來核心業務邏輯 的情況下,對函式或類物件進行額外的修飾。python中的裝飾器由python直譯器直接支援,其定義形式如下 decorator def core service 要理解上述 的含義,我們從自定義函式裝...