【问题标题】:How pass a function with parameters as a parameter to another function in Python?如何将带有参数的函数作为参数传递给Python中的另一个函数?
【发布时间】:2019-10-09 11:57:36
【问题描述】:

我正在研究装饰器,并且通过这个例子我无法弄清楚如何访问作为 wrapper_function 中的参数(函数 display_info)发送的函数的参数而不接收然后作为参数放在 decorator_function 上.

(我想我理解 *args 和 **kwargs 的概念,但在下面的示例中,装饰器函数只能使用一个参数,但在访问 *args 中的包装器表示与一起发送的参数display_info)。

def decorator_function(originla_function):
    def wrapper_function(*args, **kwargs):
        #how wrapper accessed the arguments that weren't received on decorator_function
        print('wrapper executed before {}'.format(originla_function.__name__))
        return originla_function(*args, **kwargs)
    return wrapper_function

@decorator_function
def display_info(name, age):
    print('display_info has the following arguments ({}, {})'.format(name, age))

display_info('Bob', 29)

【问题讨论】:

    标签: python


    【解决方案1】:

    你必须明白:

    @decorator_function
    def display_info(name, age):
        # ...
    

    基本上就是:

    def display_info(name, age):
        # ...
    
    display_info = decorator_function(display_function)
    

    decorator_functiondisplay_function 函数转换为另一个函数。这仅进行一次。仅此而已,仅此而已。从现在开始,重要的是 decorator_function 返回了什么,而不是如何调用 decorator_function 来创建这个新函数。

    现在,在您的示例中,幕后发生了什么?

    @decorator_function
    def display_info(name, age):
    

    decorator_function(display_info) 的结果替换display_infodecorator_function(display_info) 返回什么?这个函数:

    def wrapper_function(*args, **kwargs):
        #how wrapper accessed the arguments that weren't received on decorator_function
        print('wrapper executed before {}'.format(display_info.__name__))
        return display_info(*args, **kwargs)
    

    请注意,我将originla_function 替换为display_info,因为decorator_functionoriginla_function 参数是原始 display_info

    所以运行display_info('Bob', 29) 调用new display_info,即wrapper_function('Bob', 29)。当wrapper_function 被这样调用时,*args 将是('Bob', 29)**kwargs** 将是{}

     return display_info(*args, **kwargs)
    

    表示返回调用原始display_info的结果。更准确地说是display_info(*('Bob', 29), **{}),它与display_info('Bob', 29) 相同。

    【讨论】:

    • 感谢 Cristian,我错过了这一步 display_info = decorator_function(display_function),现在很明显,当我运行 display_info decorator 时,我实际上是在使用其参数调用包装器。再次感谢,我错过了一个非常基本的概念!
    • glossaryPEP 318 是这方面的参考文档。
    【解决方案2】:

    在您的装饰器中,只需访问 args[0]args[1] - 这些是位置参数 你传递给任何其他方法或函数:

    print(args[0], args[1])
    

    在装饰器输出中

    Bob 29
    

    所以在你的装饰器中:

    def decorator_function(originla_function):
        def wrapper_function(*args, **kwargs):
            # Output positional arguments args[0] and args[1] or implement logic processing them
            print(args[0], args[1])
            print('wrapper executed before {}'.format(originla_function.__name__))
            return originla_function(*args, **kwargs)
        return wrapper_function
    

    *args 是您的位置(只有它们在您的案例中传递),**kwargs 是您的示例中没有使用的关键字参数。

    如果你想使用一个参数化的装饰器,它使用传递给它的参数, 这是一个例子:

    def tags(tag_name):
        def tags_decorator(func):
            def func_wrapper(name):
                return "<{0}>{1}</{0}>".format(tag_name, func(name))
            return func_wrapper
        return tags_decorator
    
    @tags("p")
    def get_text(name):
        return "Hello "+name
    
    
    if __name__=='__main__':
       print get_text("John")
    

    【讨论】:

    • 但是在 decorator_function 的定义中,我刚刚收到 original_function 作为参数,在包装器定义中它是一个函数如何能够访问位置参数 *args。
    • 接收实际参数的是wrapper_function,而不是decorator_function - decorator_function 接收函数本身。装饰是将附加行为附加到原始调用。
    • 也许我无法让自己清楚,但我不明白的是 decorator_function 接收原始函数,以及 decorator_function 访问 *args 中的包装器,因为我了解装饰器函数应该明确接收到任何函数都可以访问的参数。
    • 感谢您的回复,但根据您的说明,在它收到的标签定义(tag_name)和标签装饰器利用(func)上,该定义到底如何具有与当标签首先没有收到参数时,通过调用 get_text 传递参数,但内部函数继续能够使用它。
    • Python 中装饰的工作方式是外部作用域接收实际函数,内部作用域定义接收将行为附加到该函数,接收位置和关键字参数。在内部范围内返回更新的函数调用,在外部范围内返回实际的函数定义。这简化为用作装饰器的语法糖。
    猜你喜欢
    • 1970-01-01
    • 2019-04-23
    • 2013-11-19
    • 1970-01-01
    • 2017-08-07
    • 2019-10-09
    • 2010-10-22
    • 1970-01-01
    相关资源
    最近更新 更多