实现 python 装饰器以将函数传递给另一个函数

Posted

技术标签:

【中文标题】实现 python 装饰器以将函数传递给另一个函数【英文标题】:Implement python decorator for passing down the function to another function 【发布时间】:2021-01-14 11:42:21 【问题描述】:

我想设计一个python decorator,它接受一个经过修饰的函数并将其传递给另一个函数。这是我正在尝试做的代码解释:

def run_decorator(run_batch):                                                                                                
    # inner function can access the outer local                                                                            
    # functions like in this case "func"                                                                                   
    def check(command_to_run):                                                                                             
        @functools.wraps(command_to_run)                                                                                             
        def wrapper(*args, **kwargs):
            batch_json_path = kwargs['batch_json_path']                                                                    
            batch_name = kwargs['batch_name']                                                                              
            folder_path = kwargs['folder_path']                                                                            
            if batch_json_path is not None:                                                                                
                if batch_present(batch_json_path, batch_name):
                    run_batch(batch_json_path, command_to_run, batch_name)
         return wrapper
    return check

def run_batch(batch_abs_path, command_to_run, batch_name=None):
    with open(batch_abs_path) as json_file:
        variant = ...
        tag_data = ...
        command_to_run(variant, batch_name, tag_data)

@run_decorator(run_batch=run_batch)                                                                                                         
def load_tag_for_variant(variant, batch_name, tag_data):

这样的行为可能实现吗?任何建议将不胜感激。

【问题讨论】:

这会有帮助吗? ***.com/questions/27342149/decorator-execution-order 对我来说,代码非常合理,应该可以工作。你的问题到底是什么? 我猜主要的问题是我不完全确定如何同时将参数传递给两个函数(run_batch 和 command_to_run)。 我需要将 3 个参数传递给装饰器:batch_json_path、batch_name 和 folder_path,它们不是 load_tag_for_variant 函数的参数,但应该在程序运行时以某种方式输入到装饰器/load_tag_for_variant。 【参考方案1】:

您在评论中指出:I need to pass to the decorator 3 parameters: batch_json_path, batch_name and folder_path which are not the parameters of the load_tag_for_variant function, but should somehow be fed into the decorator / load_tag_for_variant at the moment program runs.

据我了解,您想在装饰时传递这些参数。为此,您应该将它们传递给run_decorator 函数。

def run_decorator(run_batch, batch_json_path, batch_name, folder_path):                                                                                                                                                                               
    def check(command_to_run):                                                                                             
        @functools.wraps(command_to_run)                                                                                             
        def wrapper(*args, **kwargs):                                                                        
            if batch_json_path is not None:                                                                                
                if batch_present(batch_json_path, batch_name):
                    run_batch(batch_json_path, batch_name, command_to_run, *args, **kwargs)
         return wrapper
    return check
    
@run_decorator(run_batch, batch_json_path="a_path", batch_name="a_name", folder_path="a_path")                                                                                                         
def load_tag_for_variant(variant, batch_name, tag_data):
    ...

您还想将调用装饰函数的 args (variant, batch_name, tag_data) 和 kwargs 传递给原始函数 (load_tag_for_variant/command_to_run)。使用示例函数,您可以这样做:

def run_batch(batch_abs_path, batch_name, command_to_run, *args, **kwargs):
    command_to_run(*args, **kwargs)
    ...

鉴于您有两次batch_name,我不确定您是希望在装饰时还是在函数调用时定义它。例如,如果您只想从 kwargs 获取它,您可以使用 kwargs.get('batch_name')

【讨论】:

以上是关于实现 python 装饰器以将函数传递给另一个函数的主要内容,如果未能解决你的问题,请参考以下文章

在 Python 中,如何获取带参数传递给装饰器的函数名称?

将命令行参数传递给调用带有装饰器参数的装饰函数的函数

Python - 将一个函数传递给另一个函数

将带参数的函数传递给Python中的另一个函数?

将变量从一个函数传递给另一个类的另一个函数 - Python

python在定义类的时候,如何把类函数传递给另一个变量,如下