Python 裝飾器
什麼是裝飾器
裝飾器就是把一個函數當參數傳到另一個函數(也可以是可迭代對象 callable
)中,然後再回調, @
是其語法糖
常見的四種形態的裝飾器
1. 不帶參數的裝飾器
def logger(func):
def wrapper(*args, **kwargs):
print(f'prepare to run {func.__name__}')
func(*args, **kwargs)
print('finished...')
return wrapper
@logger
def add(x, y):
print(f'{x} + {y} = {x+y}')
add(1, 2)
2. 帶參數的裝飾器
def logger(level='INFO'):
def wrapper(func):
def handle(*args, **kwargs):
print(f'{level}: prepare to run {func.__name__}')
func(*args, **kwargs)
print('finished...')
return handle
return wrapper
@logger('ERROR')
def add(x, y):
print(f'{x} + {y} = {x+y}')
add(1, 2)
3. 不帶參數的類裝飾器
不帶參數時,初始化的參數爲被裝飾函數
,即兩層結構。
class logger(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print(f'{self.level}: prepare to run {func.__name__}')
return self.func(*args, **kwargs)
@logger
def add(x, y):
print(f'{x} + {y} = {x+y}')
add(1, 2)
4. 帶參數的類裝飾器
帶參數時,初始化的參數爲裝飾函數的參數
,即三層結構。
class logger(object):
def __init__(self, level="INFO"):
self.level = level
def __call__(self, func):
def wrapper(*args, **kwargs):
print(f'{self.level}: prepare to run {func.__name__}')
return func(*args, **kwargs)
return wrapper
@logger('ERROR')
def add(x, y):
print(f'{x} + {y} = {x+y}')
add(1, 2)
使用裝飾器的注意事項
1. 使用 functools 中的 wraps
保持被裝飾函數簽名, 否則簽名爲裝飾器對象
from functools import wraps
def wrapper(func):
@wraps(func)
def handle():
pass
return handle
@wrapper
def wrapped():
pass
print(wrapped.__name__)
# wrapped
2. 裝飾順序
執行順序: wrapper1 > wrapper2 (wrapper1 裝飾 wrapper2, wrapper2 裝飾 func)
@wrapper1
@wrapper2
def func():
pass
3. 閉包
def counter(func):
def wrapper(*args, **kwargs):
wrapper.count = wrapper.count + 1
res = func(*args, **kwargs)
print("{0} has been used: {1}x".format(func.__name__, wrapper.count))
return res
wrapper.count = 0
return wrapper
@counter
def system_out(string):
print(string)
system_out("A")
system_out("B")
# A
# system_out has been used: 1x
# B
# system_out has been used: 2x
裝飾器常用場景及代碼實現
日誌打印,權限控制,處理函數超時(待更新)
參考
https://stackoverflow.com/que...