为了账号安全,请及时绑定邮箱和手机立即绑定

为什么装饰器函数具有返回值?

为什么装饰器函数具有返回值?

MMMHUHU 2022-08-25 13:40:47
请考虑以下示例。def decorator(function_to_decorate):    def wrapper():        print('Entering', function_to_decorate.__name__)        function_to_decorate()        print('Exiting', function_to_decorate.__name__)    return wrapper@decoratordef func():    print("Original function.")func()由于语法只是 的简写,因此必须返回某些内容是合乎逻辑的。我的问题是:为什么装饰器以这种方式定义,而不是没有返回值:?返回包装器函数的目的是什么?@decoratorfunc = my_decorator(func)my_decoratormy_decorator(func)wrapper编辑装饰器如何比简单的包装器做得更多?def wrapper(function_to_decorate):    print('Entering', function_to_decorate.__name__)    function_to_decorate()    print('Exiting', function_to_decorate.__name__)def func():    print("Original function.")wrapper(func)
查看完整描述

1 回答

?
芜湖不芜

TA贡献1796条经验 获得超7个赞

想象一下,如果您可以将装饰器应用于常规变量赋值,如下所示:


def add1(x):

    return x + 1


@add1

number = 5

与函数修饰器类似的行为如下所示:


number = 5

number = add1(number)

这将导致将值赋给变量 。现在想象一下,装饰器只是被调用而没有返回任何内容:6number


number = 5

add1(number)

此代码不可能分配给变量 ,因为它是按值传递的,而不是通过引用传递的;在Python中,函数不能将新值分配给它无权访问的完全不同作用域中的变量。6numbernumber


语句实际上是一种赋值;它将函数分配给您用来定义它的名称。例如,函数定义编译为字节码,执行 ,即赋值:defdef func(): passSTORE_NAME


  1     0 LOAD_CONST         0 (<code object func at ...>)

        3 LOAD_CONST         1 ('func')

        6 MAKE_FUNCTION      0

        9 STORE_NAME         0 (func)

因此,出于同样的原因,功能装饰器的行为与上述方式相同;装饰器函数无法将新函数重新分配给完全不同作用域中的变量,因为它是按值传递给装饰器的,而不是通过引用传递的。funcfunc


这种等价性实际上有点误导。为了完全正确起见,当您使用修饰器时,您在语句中定义的函数将直接传递给装饰器,而不是在传递之前分配给本地名称。下面是字节码:func = decorator(func)deffunc


  1     0 LOAD_NAME          0 (decorate)

        3 LOAD_CONST         0 (<code object func at ...>)

        6 LOAD_CONST         1 ('func')

        9 MAKE_FUNCTION      0

       12 CALL_FUNCTION      1 (1 positional, 0 keyword pair)

       15 STORE_NAME         1 (func)

循序渐进:

  • 该函数被加载到堆栈上,decorate

  • 的代码对象被加载到堆栈上,然后是字符串,然后指令将这两个转换为一个函数,该函数保留在堆栈上。func'func'MAKE_FUNCTION

  • 该指令使用一个参数(函数)调用函数(仍在堆栈上)。CALL_FUNCTIONdecoratefunc

  • 无论函数返回什么,都留在堆栈上,并由指令分配给名称。decoratefuncSTORE_NAME

因此,如果函数没有返回任何内容,则不会为名称分配任何内容 - 甚至不会像语句中的原始函数那样。decoratorfuncdef


查看完整回答
反对 回复 2022-08-25
  • 1 回答
  • 0 关注
  • 75 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号