裝飾器是什麼意思
一個大牛舉的例子:
內褲可以用來遮羞,但是到了冬天它沒法爲我們防風禦寒,聰明的人們發明了長褲,有了長褲後寶寶再也不冷了,裝飾器就像我們這裏說的長褲,在不影響內褲作用的前提下,給我們的身子提供了保暖的功效。
裝飾器本質上是Python函數,可以爲已存在的對象添加額外的功能,同時裝飾器還可以抽離出與函數無關的重用代碼。具體應用場景如:插入日誌、性能測試、事務處理、緩存、權限校驗等。
舉個栗子
需要在某個原有功能上加一層驗證
def a():
print 'a'
def b():
print 'a'
a b 方法很多地方調用,不想更改原有調用方式
即:
def a():
權限驗證
print 'a'
def b():
權限驗證
print 'a'
假如有很多的接口—-
用裝飾器來實現:
def auth(func):
def inner():
# 驗證1
return func()
return inner
@auth
def a():
print 'a'
@auth
def a():
print 'b'
帶參數裝飾器
執行方法帶參數
def auth(func):
def inner(arg1,arg2):
# 驗證1
return func(arg1,arg2)
return inner
@auth
def a(arg1,arg2):
print 'a'
@auth
def b(arg1,arg2):
print 'b'
裝飾器帶參數
def auth(info):
def decorator(func):
def inner(arg1,arg2):
# 驗證1
print info
return func(arg1,arg2)
return inner
return decorator
@auth(info='a')
def a(arg1,arg2):
print 'a'
@auth(info='b')
def b(arg1,arg2):
print 'b'
類裝飾器
再來看看類裝飾器,相比函數裝飾器,類裝飾器具有靈活度大、高內聚、封裝性等優點。使用類裝飾器還可以依靠類內部的__call__方法,當使用 @ 形式將裝飾器附加到函數上時,就會調用此方法。
class Foo(object):
def __init__(self, func):
self._func = func
def __call__(self):
print ('class decorator runing')
self._func()
print ('class decorator ending')
@Foo
def bar():
print ('bar') bar()
裝飾器執行順序
@a
@b
@c
def f ():
等於
f = a(b(c(f)))
帶來的問題(知乎劉志軍大牛)
使用裝飾器極大地複用了代碼,但是他有一個缺點就是原函數的元信息不見了,比如函數的docstring、name、參數列表
這個問題就比較嚴重的,好在我們有functools.wraps,wraps本身也是一個裝飾器,它能把原函數的元信息拷貝到裝飾器函數中,這使得裝飾器函數也有和原函數一樣的元信息了。
from functools import wraps
def logged(func):
@wraps(func)
def with_logging(*args, **kwargs):
print func.__name__ + " was called"
return func(*args, **kwargs)
return with_logging
@logged
def f(x):
"""does some math"""
return x + x * x
print f.__name__ # prints 'f'
print f.__doc__ # prints 'does some math'