如何在装饰器和装饰函数之间获取相同的/传递参数?

时间:2017-02-28 13:37:25

标签: python python-3.x parameters decorator python-decorators

在这种情况下,我想将_source_dir_abs:str传递给装饰者。

我试图模仿Flask用于路由的相同过程,以便将参数从装饰器传递到它被装饰的功能。但这使得参数被解释为文字字符串而不是变量。

@dec_check_abs("<_source_dir_abs>")
def walk_return_dir_nofolder(_source_dir_abs:str) -> list:
    w = walk(_source_dir_abs)
    d = [d for d, fol, fil in w if len(fol) == 0]
    return d

我尝试使用@dec_check_abs(_source_dir_abs)时返回错误NameError: name 'source_dir_abs' is not defined

def dec_check_abs(*args_1):
    def decorator(_func:FT):
        def wrapper(*args_2, **kwargs):
            for i in args_1:
                if not check_abs(i):
                    """Raise warning."""
                    napw()

                    if _func.__annotations__["return"] == bool:
                        return False
                    else:
                        return None

            return _func(*args_2, **kwargs)
        return wrapper
    return decorator

2 个答案:

答案 0 :(得分:0)

你错过了装饰者的观点。你没有在装饰器声明中传递参数;该装饰器返回的函数接受参数,并在必要时将其传递给包装函数。

所以装饰器看起来像这样:

def dec_check_abs(func):
    def wrapper(*args):
        if ... do your check on args here...:
            return func(*args)
        else:
            print('No, bad caller.')
    return wrapper

你只需将其用作:

@dec_check_abs
def walk_return_dir_nofolder(_source_dir_abs:str) -> list:
    ...

答案 1 :(得分:0)

我在Reddit帖子https://www.reddit.com/r/learnpython/comments/5wnygi/how_can_i_get_the_same_parameters_between/中回答了我的问题。

现在是我的代码。

def dec_check_abs(*params):
    def decorator(func):
        sig = inspect.signature(func)
        def wrapper(*args, **kwargs):
            bound = sig.bind(*args, **kwargs)
            for param in params:
                val = bound.arguments[param]

                if not check_abs(val):
                    """Raise warning."""
                    napw()

                    if sig.return_annotation == bool:
                        return False
                    else:
                        return None

            return func(*args, **kwargs)
        return wrapper
    return decorator

@dec_check_abs("source_dir_abs")
def check_isfolder(source_dir_abs:str) -> bool:
    return os.path.isdir(source_dir_abs)

@dec_check_abs("source_dir_abs", "dest_dir_abs")
def copy_fileorfolder(source_dir_abs:str, dest_dir_abs:str) -> bool:
    shutil.copy2(source_dir_abs, dest_dir_abs)
    return True