语法糖@:
@dec
def f():
pass
# 等价于
f = dec(f)
@dec(x)
def f():
pass
f = dec(x)(f)
写装饰器套路
装饰器是否需要配置
def dec(f): #装饰器函数
do_something(f)
def wrapper(*args ,**kwargs):
preprocess()
result = f(*args, **kwargs)
postprocess()
return result
return wrapper
@dec
def f():
pass
原函数是否需要包装
def dec_3(*opts): #配置函数
def dec(f): #装饰器函数
def wrapper(*args, **kwargs): #包装函数
# do something
return f(*args, **kwargs)
return dec
demo 可带参数,又可省略的装饰器
体会python没有重载机制,通过灵活的传参,覆盖大多数重载的需求
from functools import wraps
tasks = []
def count(f):
counter = 0
@wraps(f)
def wrapper(*args, **kwargs):
nonlocal counter
counter += 1
return f(*args, **kwargs) + ' '+str(counter)
#update_wrapper(wrapper, f)
return wrapper
def update_wrapper(wrapper, wrapped):
setattr(wrapper, '__name__', wrapped.__name__)
#让装饰器既可以接收参数,又可以接收函数。
def task(name = ''):
# 通过动态分析参数类型,来区分功能
if callable(name):
#如果没有传配置,相当于_task(f)
return task()(name)
def _task(f):
global tasks
tasks.append(f)
if name:
setattr(f,'name', name)
else:
setattr(f, 'name', f.__name__) #封装细节
return f
return _task
@task
def play():
return 'playing ...'
@task("投币")
@count
def coin():
return "ding!"
def action():
for task in tasks:
print(task.name, ":", task())
if __name__ == '__main__':
action();
action();
action();