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 装饰器可以用来改变函数返回的函数的行为吗?的主要内容,如果未能解决你的问题,请参考以下文章

Python开发第十四篇装饰器

Python 中的装饰器

python装饰器

Python入门5

Python装饰器

python再议装饰器