python裝飾器詳解

2021-08-20 06:34:35 字數 4849 閱讀 8211

「你會python嘛?」

「我會!」

『那你給我講下python裝飾器吧!』

「python裝飾器啊?我沒用過哎」

簡言之,python裝飾器就是用於拓展原來函式功能的一種函式,這個函式的特殊之處在於它的返回值也是乙個函式,使用python裝飾器的好處就是在不用更改原函式的**前提下給函式增加新的功能。

一般而言,我們要想拓展原來函式**,最直接的辦法就是侵入**裡面修改,例如:

import

time

deffunc():

print("hello"

) time.sleep(1

) print("world"

)

這是我們最原始的的乙個函式,然後我們試圖記錄下這個函式執行的總時間,那最簡單的做法就是:

#原始侵入,篡改原函式

import

time

deffunc():

starttime = time.time()

print("hello"

) time.sleep(1

) print("world"

) endtime = time.time()

msecs = (endtime - starttime)*1000

print("time is %d ms"

%msecs)

但是如果你的boss在公司裡面和你說:「小祁,這段**是我們公司的核心**,你不能直接去改我們的核心**。」那該怎麼辦呢,我們仿照裝飾器先自己試著寫一下:

#避免直接侵入原函式修改,但是生效需要再次執行函式

import

time

defdeco

(func)

: starttime = time.time()

func()

endtime = time.time()

msecs = (endtime - starttime)*1000

print("time is %d ms"

%msecs)

deffunc():

print("hello"

) time.sleep(1

) print("world")if

__name__ == '__main__'

: f = func

deco(f)#只有把func()或者f()作為引數執行,新加入功能才會生效

print("f.__name__ is"

,f.__name__)#f的name就是func()

print()

#func()

這裡我們定義了乙個函式deco,它的引數是乙個函式,然後給這個函式嵌入了計時功能。然後你可以拍著胸脯對老闆說,看吧,不用動你原來的**,我照樣拓展了它的函式功能。

然後你的老闆有對你說:「小祁,我們公司核心**區域有一千萬個func()函式,從func01()到func1kw(),按你的方案,想要拓展這一千萬個函式功能,就是要執行一千萬次deco()函式,這可不行呀,我心疼我的機器。」

好了,你終於受夠你老闆了,準備辭職了,然後你無意間聽到了裝飾器這個神器,突然發現能滿足你閆博士的要求了。

我們先實現乙個最簡陋的裝飾器,不使用任何語法糖和高階語法,看看裝飾器最原始的面貌:

#既不需要侵入,也不需要函式重複執行

import

time

defdeco

(func)

: def():

starttime = time.time()

func()

endtime = time.time()

msecs = (endtime - starttime)*1000

print("time is %d ms"

%msecs)

return

@deco

deffunc():

print("hello"

) time.sleep(1

) print("world")if

__name__ == '__main__'

: f = func #這裡f被賦值為func,執行f()就是執行func()

f()

#帶有引數的裝飾器

import

time

defdeco

(func)

: def

(a,b)

: starttime = time.time()

func(a,b)

endtime = time.time()

msecs = (endtime - starttime)*1000

print("time is %d ms"

%msecs)

return

@deco

deffunc

(a,b)

: print("hello,here is a func for add :"

) time.sleep(1

) print("result is %d"

%(a+b))

if __name__ == '__main__'

: f = func

f(3,4)

#func()

然後你滿足了boss的要求後,boss又說:「小祁,我讓你拓展的函式好多可是有引數的呀,有的引數還是個數不定的那種,你的裝飾器搞的定不?」然後你嘿嘿一笑,深藏功與名!

#帶有不定引數的裝飾器

import

time

defdeco

(func)

: def

(*args, **kwargs)

: starttime = time.time()

func(*args, **kwargs)

endtime = time.time()

msecs = (endtime - starttime)*1000

print("time is %d ms"

%msecs)

return

@deco

deffunc

(a,b)

: print("hello,here is a func for add :"

) time.sleep(1

) print("result is %d"

%(a+b))

@deco

deffunc2

(a,b,c)

: print("hello,here is a func for add :"

) time.sleep(1

) print("result is %d"

%(a+b+c))

if __name__ == '__main__'

: f = func

func2(3

,4,5

) f(3,4)

#func()

最後,你的老闆說:「可以的,小祁,我這裡乙個函式需要加入很多功能,乙個裝飾器怕是搞不定,裝飾器能支援多個嘛」

最後你就把這段**丟給了他:

#多個裝飾器

import

time

defdeco01

(func)

: def

(*args, **kwargs)

: print("this is deco01"

) starttime = time.time()

func(*args, **kwargs)

endtime = time.time()

msecs = (endtime - starttime)*1000

print("time is %d ms"

%msecs)

print("deco01 end here"

) return

defdeco02

(func)

: def

(*args, **kwargs)

: print("this is deco02"

) func(*args, **kwargs)

print("deco02 end here"

) return

@deco01

@deco02

deffunc

(a,b)

: print("hello,here is a func for add :"

) time.sleep(1

) print("result is %d"

%(a+b))

if __name__ == '__main__'

: f = func

f(3,4)

#func()

'''this is deco01

this is deco02

hello,here is a func for add :

result is 7

deco02 end here

time is 1003 ms

deco01 end here

'''

多個裝飾器執行的順序就是從第乙個裝飾器開始,執行到最後乙個裝飾器,再執行函式本身。

參考:python 裝飾器:

python裝飾器 python 裝飾器詳解

def outer x def inner y return x y return inner print outer 6 5 11 如 所示,在outer函式內,又定義了乙個inner函式,並且inner函式又引用了外部函式outer的變數x,這就是乙個閉包了。在輸出時,outer 6 5 第乙個...

python裝飾器詳解 python裝飾器詳解

按照 python 的程式設計原則,當乙個函式被定義後,如要修改或擴充套件其功能應盡量避免直接修改函式定義的 段,否則該函式在其他地方被呼叫時將無法正常執行。因此,當需要修改或擴充套件已被定義的函式的功能而不希望直接修改其 時,可以使用裝飾器。先來看乙個簡單的例子 def func1 functio...

詳解Python裝飾器

裝飾器的難點 在梳理了裝飾器的整個內容之後,我認為難點不是裝飾器本身,而是直接呼叫被裝飾的函式,讓人無法理解背後究竟發生了什麼。一 引出裝飾器概念 引入問題 定義了乙個函式,想在執行時動態的增加功能,又不想改動函式本身的 示例 希望對下列函式呼叫增加log功能,列印出函式呼叫 def f1 x re...