python 装饰器可以用来改变函数返回的函数的行为吗?
Posted
技术标签:
【中文标题】python 装饰器可以用来改变函数返回的函数的行为吗?【英文标题】:Can python decorators be used to change behavior of a function returned by a function? 【发布时间】:2020-02-12 21:07:08 【问题描述】:我有函数,返回验证器函数,简单示例:
def check_len(n):
return lambda s: len(s) == n
是否可以添加一个装饰器,打印出一条消息,以防检查评估为假? 像这样的:
@log_false_but_how
def check_len(n):
return lambda s: len(s) == n
check_one = check_len(1)
print(check_one('a')) # returns True
print(check_one('abc')) # return False
预期输出:
True
validator evaluated to False
False
我尝试过创建注释,但只能使用它访问函数创建。 一种方法是定义如下函数:
def log_false(fn):
def inner(*args):
res = fn(*args)
if not res:
print("validation failed for ".format(fn.__name__))
return res
return inner
@log_false
def check_one(s):
return check_len(1)(s)
但是这样我们就失去了验证函数的动态创建。
【问题讨论】:
为什么不将日志记录添加为check_len(n)
函数本身的一部分?
您走在正确的轨道上,并且已经完成了一半。剩下的就是将另一个装饰器应用到 res
并返回它而不是 res
。
@rdas 因为我有很多验证函数,并且在验证器工厂中添加装饰器更简单,所以验证逻辑和错误显示/记录逻辑也是分开的问题。
【参考方案1】:
您在错误的位置进行验证。 check_len
是一个函数工厂,所以 res
不是布尔值 - 它是一个函数。您的@log_false
装饰器必须围绕check_len
返回的每个lambda 包装一个验证器函数。基本上你需要编写一个装饰器来装饰返回的函数。
def log_false(validator_factory):
# We'll create a wrapper for the validator_factory
# that applies a decorator to each function returned
# by the factory
def check_result(validator):
@functools.wraps(validator)
def wrapper(*args, **kwargs):
result = validator(*args, **kwargs)
if not result:
name = validator_factory.__name__
print('validation failed for '.format(name))
return result
return wrapper
@functools.wraps(validator_factory)
def wrapper(*args, **kwargs):
validator = validator_factory(*args, **kwargs)
return check_result(validator)
return wrapper
结果:
@log_false
def check_len(n):
return lambda s: len(s) == n
check_one = check_len(1)
print(check_one('a')) # prints nothing
print(check_one('abc')) # prints "validation failed for check_len"
【讨论】:
以上是关于python 装饰器可以用来改变函数返回的函数的行为吗?的主要内容,如果未能解决你的问题,请参考以下文章