python装饰器_Python基础-装饰器
概述
裝飾器其實就是一個函數,返回值是一個函數對象,它可以讓其他函數在不需要做任何代碼改動的前提下增加額外功能,比如:日志功能、性能測試、緩存、事務處理、權限校驗等。
為了理解裝飾器,我們要先理解一個概念,即:python里面一切皆對象,包括函數。
函數裝飾器詳解
最簡單的裝飾器
def my_decorator(f):return f這個裝飾器什么也沒做,返回原函數對象。
裝飾器的使用
def my_decorator(f):return f@my_decorator def fun():print('zarten')fun()上面代碼等價于:
def my_decorator(f):return fdef fun():print('zarten')fun = my_decorator(fun) fun()一般使用第一種方式,python中特有的裝飾器語法,更加簡潔。
裝飾器返回另外一個函數
裝飾器通常都是返回另外一個函數,而不是原函數本身
def my_decorator(f):def other_fun():print('other_fun')return other_fun@my_decorator def fun():print('zarten')fun() print(fun)調用fun()函數,其實是運行裝飾器里面的other_fun()函數。從輸出結果也可看到,fun()函數現在是other_fun()函數的引用。
從輸出結果可以看到,并沒有執行fun()函數內的代碼,這是因為在裝飾器內部執行了other_fun()函數,但并沒有在內部執行fun()函數,所以一般在裝飾器傳入參數,這個參數是被裝飾的函數對象,都會在裝飾器內部調用并返回其結果
def my_decorator(f):def other_fun():print('other_fun')return f()return other_fun@my_decorator def fun():print('zarten')fun() print(fun)functools.wraps的作用
我們知道,執行fun()函數,實際上是執行了裝飾器里面的other_fun()函數,并在內部返回了原函數。但這樣有個缺點是:原函數的一些元信息發生了改變,如docstring、__name__、參數列表等。如下代碼所示:
def my_decorator(f):def other_fun():print('other_fun')return f()return other_fun@my_decorator def fun():print('zarten')print('fun name:', fun.__name__)為了防止元信息改變,python引入了functools.wraps,用法如下
from functools import wraps def my_decorator(f):@wraps(f)def other_fun():print('other_fun')return f()return other_fun@my_decorator def fun():print('zarten')print('fun name:', fun.__name__)一個完整簡單的日志打印裝飾器
from functools import wrapsdef my_decorator(f):@wraps(f)def other_fun(*args, **kwargs):print('%s in running' % f.__name__)return f(*args, **kwargs)return other_fun@my_decorator def fun():print('zarten')fun()帶參數的裝飾器
裝飾器是把被裝飾函數作為第一個參數傳進去,若裝飾器帶有參數時,怎么接收其他額外的參數呢?
方法是:將額外的參數作為第一個參數傳進去,然后返回一個函數對象,這個函數的參數才是被裝飾函數的對象
from functools import wrapsdef my_decorator(zhihu_id= 'zarten'):def decorator(f):@wraps(f)def other_fun(*args, **kwargs):print('%s in running.name is %s' % (f.__name__, zhihu_id))return f(*args, **kwargs)return other_funreturn decorator@my_decorator('zarten_2') def fun():print('zarten')fun()從上面代碼可以看到,裝飾器使用的默認參數,若裝飾器不傳遞任何參數時,也需要使用空括號,如@my_decorator()
類裝飾器詳解
類裝飾器,也就是說裝飾器是一個類了,而不是一個函數了。類裝飾器和函數裝飾器非常類似。
可以利用類的特殊方法__call__()來實現,實現此特殊方法后,類對象可以像函數一樣調用。PS:若對python中的常用特殊方法不了解的,可以查看我之前寫的文章,點這里。
類裝飾器的實現
class Decorator():def __init__(self, f):self.f = fdef __call__(self, *args, **kwargs):print('%s in running' % self.f.__name__)self.f(*args, **kwargs)使用類裝飾器
使用類裝飾器跟使用函數裝飾也是非常的類似
@Decorator def fun():print('zarten')fun()此時被裝飾的函數對象作為裝飾器類的參數傳入,返回一個類裝飾器的對象,由于裝飾器類里實現了__call__()的特殊方法,固可以直接調用這個對象。
若不使用@Decorator語法糖,上面代碼等價于:
def fun():print('zarten')fun = Decorator(fun) fun()完整代碼如下:
class Decorator():def __init__(self, f):self.f = fdef __call__(self, *args, **kwargs):print('%s in running' % self.f.__name__)self.f(*args, **kwargs)@Decorator def fun():print('zarten')fun()總結
以上是生活随笔為你收集整理的python装饰器_Python基础-装饰器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: apache2.4.39 php,win
- 下一篇: MATLAB信号处理工具箱函数列表分类