闭包的定义:函数的返回值为函数对象
装饰器的定义:通过装饰器,来修改原函数的一些功能,使得原函数不需要修改,就具备需要的功能。
使用内置的装饰器@functools.wrap, 保留原函数的元信息
import functools
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print('wrapper of decorator')
func(*args, **kwargs)
return wrapper
@my_decorator
def greet(message):
print(message)
print(greet.__name__) # 'greet'
常用场景:身份认证、日志记录、输入合理性检查和缓存等。
身份认证, 例如发布文章或留言的时候,判断需要登陆
import functools
def authenticate(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
request = args[0]
if check_user_logged_in(request): # 如果用户处于登录状态
return func(*args, **kwargs) # 执行函数 post_comment()
else:
raise Exception('Authentication failed')
return wrapper
@authenticate
def post_comment(request, ...)
pass
日志记录常用在测试函数的执行时间
import time
import functools
def log_execution_time(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
res = func(*args, **kwargs)
end = time.perf_counter()
print('{} took {} ms'.format(func.__name__, (end - start) * 1000))
return res
return wrapper
@log_execution_time
def calculate_similarity(items):
...
输入合理性检查,在大型公司的机器学习框架中,对其输入(往往很大的json文件) 进行合理性检查。
import functools
def validation_check(input):
@functools.wraps(func)
def wrapper(*args, **kwargs):
... # 检查输入是否合法
@validation_check
def neural_network_training(param1, param2, ...):
...
缓存,Python内置LRU cache为例
(不了解LRU cache, 自行点击链接查阅)
LRU cache, 在Python 中表现形式为@lru_cache,它会缓存进程中的函数参数和结果,缓存满了会删除最久没有访问(least recently used) 的数据。
大型公司服务器代码中往往存在很多关于设备的检查,例如安卓还是iPhone,版本号。其中一个原因是,新的feature,只适用在特殊系统或版本以上才有。
这样就可以使用缓存装饰器,包裹检查函数,避免反复调用,提高程序运行效率。
@lru_cache
def check(param1, param2, ...) # 检查用户设备类型,版本号等等
...