Python:令人困惑的函数示例作为对象

时间:2016-10-11 12:23:03

标签: python function variables python-decorators

当我重新研究装饰器的时候,我偶然发现了一些令人困惑的代码,我发现它通过变量和函数的方式令人费解。

def get_text(name):
    return "lorem ipsum, {0} dolor sit amet".format(name)

def p_decorate(func):
    def func_wrapper(name):
        return "<p>{0}</p>".format(func(name))
    return func_wrapper

my_get_text = p_decorate(get_text)

print my_get_text("John")

# <p>Outputs lorem ipsum, John dolor sit amet</p>

我理解将函数作为变量传递的概念(这很酷)但是它多次传递的方式使我感到困惑。 my_get_text已经被赋值给具有参数的函数(另一个函数)。然而,就在此之后,我们引用这个新变量并将参数传递给它(“John”)。 “约翰”在func_wrapper()转移的方式也令人困惑。

my_get_text如何能够接收更多参数以及如何将其传递给内部函数?

谢谢

1 个答案:

答案 0 :(得分:2)

这是装饰器如何工作的演示:它们基本上将装饰函数包装到另一个内部函数中并返回它的引用。

  1. 在您的示例中,调用my_get_text = p_decorate(get_text)使用可包装函数作为参数(p_decorate)调用函数get_text
  2. 返回值是对新定义的函数的引用,该函数只接受一个参数name。此返回值已分配给您的变量名称my_get_text
  3. my_get_text现在可调用,因为它是一个函数引用。
  4. 如果您致电my_get_text,则会调用由装饰器创建的功能并移交您的参数name(在您的情况下为'John')。
  5. 该函数创建<p> - 标记并在它们之间推送一个字符串。此字符串是从您在步骤1中提供装饰器的函数调用中获取的:它是已经修饰的调用的返回值。
  6. 顺便说一下,因为每次函数修饰时都会重新定义函数func_wrapper(参见 closure ),返回值是一个指向全新的函数引用功能。
    比较内存地址:

    a = p_decorate(get_text)
    b = p_decorate(get_text)
    print(a == b)
    print(a)
    print(b)
    
    >>> False
    >>> <function func_wrapper at 0x02ADFF30>
    >>> <function func_wrapper at 0x02ADFF70>
    

    函数是使用完全相同的调用定义的,但由于它们是闭包,函数指针引用另一个内存地址(即不同的函数)。