理解Python的裝飾器分爲以下6步
- 首先先理解裝飾器的含義。裝飾器本質上是一個 Python 函數或類,它可以讓其他函數或類在不需要做任何代碼修改的前提下增加額外功能,裝飾器的返回值也是一個函數/類對象。 有了裝飾器,我們就可以抽離出大量與函數功能本身無關的雷同代碼到裝飾器中並繼續重用。
- 然後瞭解下最簡單的裝飾器,也就是無函數參數的裝飾器
def use_logging1(func):
def wrapper():
logging.warn("%s is running" % func.__name__)
return func()
return wrapper
@use_logging1
def foo1():
print("i am foo")
- 帶函數參數的函數的裝飾器
def use_logging2(func):
def wrapper(*args, **kw):
logging.warn("%s is running" % func.__name__)
return func(*args, **kw)
return wrapper
@use_logging2
def foo2(name):
print("i am %s" % name)
- 帶函數參數+帶裝飾器參數的函數的裝飾器
def use_logging3(text):
def use_logging2(func):
def wrapper(*args, **kw):
logging.warn("%s is running with %s " % (func.__name__, text))
return func(*args, **kw)
return wrapper
return use_logging2
@use_logging3("decorator's args")
def foo3(name):
print("i am %s" % name)
- 因爲函數也是對象,它有__name__等屬性,但你去看經過decorator裝飾之後的函數,它們的__name__已經從原來的’now’變成了’wrapper’,有了functools.wraps()我們就不需要把原始函數的__name__等屬性複製到wrapper()函數中,它就是專門幹這事的。如下代碼塊中的foo1.__name__仍然爲foo1
def use_logging1(func):
@functools.wraps(func)
def wrapper():
logging.warn("%s is running" % func.__name__)
return func()
return wrapper
@use_logging1
def foo1():
print("i am foo")
- 應用:寫一個對任何函數的執行進行計時的裝飾器
def funcTiming(func):
@functools.wraps(func)
def wrapper():
print("begin call")
begin = time.time()
result = func()
end = time.time()
print("end call")
print('%s executed in %s ms' % (func.__name__, end - begin))
return result
return wrapper
@funcTiming
def func():
print("running")