當前位置:編程學習大全網 - 編程語言 - python decorators有什麽用?

python decorators有什麽用?

先打個形象的比方。

內衣可以用來遮羞,卻不能保護我們在冬天免受風寒。聰明人發明了褲子。有了褲子,寶寶就不再冷了。裝修工就像我們這裏說的褲子,在不影響內衣功能的前提下,給身體提供溫暖。

讓我們回到我們的話題。

裝飾器本質上是壹個Python函數,它允許其他函數添加額外的函數,而無需任何代碼更改。裝飾器的返回值也是壹個函數對象。經常用在有切片需求的場景,比如日誌插入、性能測試、事務處理、緩存、權限檢查等等。Decorator是解決這類問題的優秀設計。有了decorator,我們可以提取大量與函數本身無關的相同代碼,並繼續重用它們。簡而言之,裝飾者的作用就是給現有的對象增加額外的功能。

讓我們先看壹個簡單的例子:

def foo():

打印(“我是foo”)

現在有了新的需求,希望記錄函數的執行日誌,所以我在代碼中加入了日誌代碼:

def foo():

打印(“我是foo”)

logging.info("foo正在運行")

Bar()和bar2()也有類似的要求。我該怎麽辦?在bar函數裏再寫壹個日誌?這樣就產生了大量相同的代碼。為了減少重復寫代碼,我們可以這樣做,重新定義壹個函數:獨占處理日誌,日誌處理完後再執行真正的業務代碼。

定義使用日誌記錄(函數):

logging.warn("%s正在運行" % func。__name__)

func()定義欄():

print('我是吧')use_logging(吧)

邏輯上不難理解,

但在這種情況下,我們每次都要將壹個函數作為參數傳遞給use_logging函數。而且,這種方法破壞了原有的代碼邏輯結構。以前執行業務邏輯的時候執行bar(),現在要改成use_logging(bar)。那麽有沒有更好的辦法呢?當然,答案是decorator。

簡單裝飾

定義使用日誌記錄(函數):

def包裝(*args,**kwargs):

logging.warn("%s正在運行" % func。__name__)

return func(*args,**kwargs)

返回wrapperdef bar():

print(' I am bar ')bar = use _ logging(bar)bar()

函數use_logging是decorator,它將執行真正業務方法的func包裝在函數中,看起來就像是用use_logging裝飾了這個欄。在這個例子中,當函數進入和退出時,

稱為方面,這種編程方法稱為面向方面編程。

@符號是裝飾器的語法糖,在定義函數時使用它來避免再次賦值。

定義使用日誌記錄(函數):

def包裝(*args,**kwargs):

logging.warn("%s正在運行" % func。__name__)

返回函數(*參數)

返回包裝@use_loggingdef foo():

print("我是foo")@use_loggingdef bar():

打印(“我是吧”)吧()

如上圖所示,所以我們可以省略bar =

Use_logging(bar)。直接調用bar()來獲得想要的結果。如果我們有其他類似的函數,我們可以繼續調用裝飾器來裝飾函數,而無需重復修改函數或添加新的封裝。這樣,我們提高了程序的可重用性,增加了程序的可讀性。

在Python中使用Decorators非常方便,因為Python函數可以像普通對象壹樣作為參數傳遞給其他函數、賦給其他變量、返回值並在另壹個函數中定義。

帶參數的裝飾器

裝飾器也更加靈活,比如帶參數的裝飾器:在上面的裝飾器調用中,比如@use_logging,裝飾器唯壹的參數就是執行業務的函數。裝飾器的語法允許我們在調用時提供其他參數,比如@decorator(a)。這樣就為decorators的編寫和使用提供了更大的靈活性。

定義使用記錄(級別):

定義裝飾器(函數):

def包裝(*args,**kwargs):

如果level == "warn ":

logging.warn("%s正在運行" % func。__name__)

返回函數(*參數)

返回包裝

return decorator @ use _ logging(level = " warn ")def foo(name = ' foo '):

print("我是% s " % name ")foo()

上面的use_logging是壹個允許參數的修飾器。它實際上是原始裝飾器的壹個函數包,並返回壹個裝飾器。我們可以理解為帶參數的閉包。當我

當用戶使用@use_logging(level="warn ")調用時,Python可以找到這壹層的封裝,並將參數傳入裝飾器的環境中。

類裝飾者

讓我們來看看類裝飾。與函數裝飾器相比,類裝飾器具有很大的靈活性、高內聚性和封裝性。當使用@ form將裝飾器附加到函數時,您還可以依賴類中的\ _ \ _ call \ _ \方法。

類Foo(對象):

def __init__(self,func):

自我。_func = func

def __call__(self):

打印(“類裝飾器運行”)

自我。_func()

打印(“類裝飾結束”)

@Foo

定義欄():

打印(“條形”)

酒吧()

functools.wraps

使用decorator極大地重用了代碼,但是它有壹個缺點,就是原始函數的元信息丟失了,比如函數的docstring、__name__和參數列表。我們先來看例子:

裝飾者

記錄的定義(函數):

def with_logging(*args,**kwargs):

打印功能。__name__ +"被調用

return func(*args,**kwargs)

使用日誌記錄返回

功能

@loggeddef f(x):

"""做壹些數學運算" " "

返回x + x * x

該功能的完成相當於:

定義f(x):

"""做壹些數學運算" " "

return x + x * xf = logged(f)

不難發現,函數f被with_logging代替,當然它的docstring,__name__就變成了函數with_logging的信息。

打印f.__name__ #打印'帶_logging '打印f.__doc__ #不打印

這個問題比較嚴重。好在我們有functools.wraps本身就是壹個decorator,可以將原函數的元信息復制到decorator函數中,使得decorator函數擁有與原函數相同的元信息。

從functools導入包裝定義已記錄(func):

@wraps(func)

def with_logging(*args,**kwargs):

打印功能。__name__ +"被調用

return func(*args,**kwargs)

return with _ logging @ logged def f(x):

"""做壹些數學運算" " "

return x + x * xprint f.__name__?# prints 'f'print f.__doc__?#打印“做壹些數學”

內置裝飾品

@staticmathod 、@classmethod 、@property

裝修工的順序

@a@b@cdef f():

同族的

f = a(b(c(f)))

  • 上一篇:最好的數控編程軟件有哪些
  • 下一篇:Java開發人員需要達到的25個目標(不容易)
  • copyright 2024編程學習大全網