Python 裝飾器使用過程中的誤區

2021-08-21 17:16:51 字數 2133 閱讀 4119

大家都知道裝飾器是乙個很著名的設計模式,經常被用於aop(面向切面程式設計)的場景,較為經典的有插入日誌,效能測試,事務處理,web許可權校驗,cache等。

python語言本身提供了裝飾器語法(@),典型的裝飾器實現如下:

def function():

pass

@實際上是python2.4才提出的語法糖,針對python2.4以前的版本有另一種等價的實現:

def function():

pass

函式包裝器 – 經典實現

def function():

pass

類包裝器 – 更易於理解

def __call__(self, *args, **kwargs):

def function():

pass

當我們談到乙個函式時,通常希望這個函式的屬性像其文件上描述的那樣,是被明確定義的,例如__name____doc__

針對某個函式應用裝飾器時,這個函式的屬性就會發生變化,但這並不是我們所期望的。

def function():

pass

>>> print(function.__name__)

python標準庫提供了functools.wraps(),來解決這個問題。

import functools

def function():

pass

>>> print(function.__name__)

function

然而,當我們想要獲取被包裝函式的引數(argument)或源**(source code)時,同樣不能得到我們想要的結果。

import inspect

def function(arg1, arg2): pass

>>> print(inspect.getargspec(function))

argspec(args=, varargs='args', keywords='kwargs', defaults=none)

>>> print(inspect.getsource(function))

class class(object):

@classmethod

def cmethod(cls):

pass

traceback (most recent call last):

file "", line 1, in

file "", line 3, in class

attributeerror: 'classmethod' object has no attribute '__module__'

然而,在python3下執行,另乙個問題出現了:

class class(object):

@classmethod

def cmethod(cls):

pass

>>> class.cmethod()

traceback (most recent call last):

file "classmethod.py", line 15, in

class.cmethod()

typeerror: 'classmethod' object is not callable

這是因為包裝器認定被包裝的函式(@classmethod)是可以直接被呼叫的,但事實並不一定是這樣的。被包裝的函式實際上可能是描述符(descriptor),意味著為了使其可呼叫,該函式(描述符)必須被正確地繫結到某個例項上。關於描述符的定義,可以參考

儘管大家實現裝飾器所用的方法通常都很簡單,但這並不意味著它們一定是正確的並且始終能正常工作。

如同上面我們所看到的,functools.wraps()可以幫我們解決__name____doc__的問題,但對於獲取函式的引數(argument)或源**(source code)則束手無策。

以上問題,wrapt都可以幫忙解決,詳細用法可參考其官方文件:

Python 裝飾器使用過程中的誤區解讀

大家都知道裝飾器是乙個很著名的設計模式,經常被用於aop 面向切面程式設計 的場景,較為經典的有插入日誌,效能測試,事務處理,web許可權校驗,cache等。python語言本身提供了裝飾器語法 典型的裝飾器實現如下 deffunction pass 實際上是python2.4才提出的語法糖,針對p...

python使用過程中問題

1.檢視python支援的 whl格式 在cmd輸入python 或者 python3.6 import pip print pip.pep425tags.get supported 2.在修改python.exe為python36.exe 任何重新命名 後,pip會報錯 fatal error i...

element ui dialog使用過程中的坑

場景一 我們將dialog寫成乙個可復用的公共元件用於顯示不同內容 如 操作中的修改或新增的彈窗 之後發現dialog的遮罩將彈出層 點選修改或新增後理應由乙個彈窗顯示出來 都蓋住了,而我想要的效果是遮罩只遮住舊的視窗,而當前視窗應該完全顯示 注 是使用easyui的panel和window來包裹的...