Python 函式裝飾器 1

2021-08-28 09:27:59 字數 2219 閱讀 9495

先看這篇,簡單講解了一下,但是不全面

再看這篇,簡單直觀的了解一下裝飾器:

裝飾模式有很多經典的使用場景,例如插入日誌、效能測試、事務處理等等,有了裝飾器,就可以提取大量函式中與本身功能無關的類似**,從而達到**重用的目的。下面就一步步看看python中的裝飾器。

乙個簡單的需求

現在有乙個簡單的函式」myfunc」,想通過**得到這個函式的大概執行時間。

我們可以直接把計時邏輯方法」myfunc」內部,但是這樣的話,如果要給另乙個函式計時,就需要重複計時的邏輯。所以比較好的做法是把計時邏輯放到另乙個函式中(」deco」),如下:

但是,上面的做法也有乙個問題,就是所有的」myfunc」呼叫處都要改為」deco(myfunc)」。

下面,做一些改動,來避免計時功能對」myfunc」函式呼叫**的影響:

經過了上面的改動後,乙個比較完整的裝飾器(deco)就實現了,裝飾器沒有影響原來的函式,以及函式呼叫的**。例子中值得注意的地方是,python中一切都是物件,函式也是,所以**中改變了」myfunc」對應的函式物件。

裝飾器語法糖

在python中,可以使用」@」語法糖來精簡裝飾器的**:

使用了」@」語法糖後,我們就不需要額外**來給」myfunc」重新賦值了,其實」@deco」的本質就是」myfunc = deco(myfunc)」,當認清了這一點後,後面看帶引數的裝飾器就簡單了。

被裝飾的函式帶引數

前面的例子中,被裝飾函式的本身是沒有引數的,下面看乙個被裝飾函式有引數的例子:

從例子中可以看到,對於被裝飾函式需要支援引數的情況,我們只要使裝飾器的內嵌函式支援同樣的簽名即可。

也就是說這時,」addfunc(3, 8) = deco(addfunc(3, 8))」。

這裡還有乙個問題,如果多個函式擁有不同的引數形式,怎麼共用同樣的裝飾器?在python中,函式可以支援(*args, **kwargs)可變引數,所以裝飾器可以通過可變引數形式來實現內嵌函式的簽名。

帶引數的裝飾器

裝飾器本身也可以支援引數,例如說可以通過裝飾器的引數來禁止計時功能:

通過例子可以看到,如果裝飾器本身需要支援引數,那麼裝飾器就需要多一層的內嵌函式。

這時候,」addfunc(3, 8) = deco(true)( addfunc(3, 8))」,」myfunc() = deco(false)( myfunc ())」。

裝飾器呼叫順序

裝飾器是可以疊加使用的,那麼這是就涉及到裝飾器呼叫順序了。對於python中的」@」語法糖,裝飾器的呼叫順序與使用 @ 語法糖宣告的順序相反。

在這個例子中,」addfunc(3, 8) = deco_1(deco_2(addfunc(3, 8)))」。

python內建裝飾器

對於staticmethod和classmethod這裡就不介紹了,通過乙個例子看看property。

注意,對於python新式類(new-style class),如果將上面的 「@var.setter」 裝飾器所裝飾的成員函式去掉,則foo.var 屬性為唯讀屬性,使用 「foo.var = 『var 2′」 進行賦值時會丟擲異常。但是,對於python classic class,所宣告的屬性不是 read-only的,所以即使去掉」@var.setter」裝飾器也不會報錯。

參考:

python裝飾器 函式裝飾器,類裝飾器

只要實現此 模式,這個obj就叫乙個裝飾器 參考 函式裝飾器 例子 def decorator func def inner args,kwargs print before.res func args,kwargs print after.return res return inner decor...

python 裝飾器 函式裝飾器 類裝飾器

python函式裝飾器和類裝飾器筆記.usr bin env python coding utf 8 author ivan file decorators.py version from functools import wraps 裝飾器 目的是為了給函式新增附加功能 1.不帶引數裝飾器 此方式...

python裝飾器 裝飾器工廠函式

使用裝飾器實現如下所示的列印 小白聯盟def printequel func1 def inner1 print 15 func1 return inner1 def printstar func2 def inner2 print 15 func2 return inner2 printequel...