python 装饰器可以用来改变函数返回的函数的行为吗?
Can python decorators be used to change behavior of a function returned by a function?
我有函数,return 验证器函数,简单示例:
def check_len(n):
return lambda s: len(s) == n
是否可以添加一个装饰器,打印出一条消息,以防检查结果为 false?
像这样:
@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
是一个函数工厂,所以 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"
我有函数,return 验证器函数,简单示例:
def check_len(n):
return lambda s: len(s) == n
是否可以添加一个装饰器,打印出一条消息,以防检查结果为 false? 像这样:
@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
是一个函数工厂,所以 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"