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

请考虑以下示例。


def decorator(function_to_decorate):

    def wrapper():

        print('Entering', function_to_decorate.__name__)

        function_to_decorate()

        print('Exiting', function_to_decorate.__name__)

    return wrapper


@decorator

def 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)


MMMHUHU
浏览 76回答 1
1回答

芜湖不芜

想象一下,如果您可以将装饰器应用于常规变量赋值,如下所示:def add1(x):&nbsp; &nbsp; return x + 1@add1number = 5与函数修饰器类似的行为如下所示:number = 5number = add1(number)这将导致将值赋给变量 。现在想象一下,装饰器只是被调用而没有返回任何内容:6numbernumber = 5add1(number)此代码不可能分配给变量 ,因为它是按值传递的,而不是通过引用传递的;在Python中,函数不能将新值分配给它无权访问的完全不同作用域中的变量。6numbernumber语句实际上是一种赋值;它将函数分配给您用来定义它的名称。例如,函数定义编译为字节码,执行 ,即赋值:defdef func(): passSTORE_NAME&nbsp; 1&nbsp; &nbsp; &nbsp;0 LOAD_CONST&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 (<code object func at ...>)&nbsp; &nbsp; &nbsp; &nbsp; 3 LOAD_CONST&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 ('func')&nbsp; &nbsp; &nbsp; &nbsp; 6 MAKE_FUNCTION&nbsp; &nbsp; &nbsp; 0&nbsp; &nbsp; &nbsp; &nbsp; 9 STORE_NAME&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 (func)因此,出于同样的原因,功能装饰器的行为与上述方式相同;装饰器函数无法将新函数重新分配给完全不同作用域中的变量,因为它是按值传递给装饰器的,而不是通过引用传递的。funcfunc这种等价性实际上有点误导。为了完全正确起见,当您使用修饰器时,您在语句中定义的函数将直接传递给装饰器,而不是在传递之前分配给本地名称。下面是字节码:func = decorator(func)deffunc&nbsp; 1&nbsp; &nbsp; &nbsp;0 LOAD_NAME&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 (decorate)&nbsp; &nbsp; &nbsp; &nbsp; 3 LOAD_CONST&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 (<code object func at ...>)&nbsp; &nbsp; &nbsp; &nbsp; 6 LOAD_CONST&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 ('func')&nbsp; &nbsp; &nbsp; &nbsp; 9 MAKE_FUNCTION&nbsp; &nbsp; &nbsp; 0&nbsp; &nbsp; &nbsp; &nbsp;12 CALL_FUNCTION&nbsp; &nbsp; &nbsp; 1 (1 positional, 0 keyword pair)&nbsp; &nbsp; &nbsp; &nbsp;15 STORE_NAME&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 (func)循序渐进:该函数被加载到堆栈上,decorate的代码对象被加载到堆栈上,然后是字符串,然后指令将这两个转换为一个函数,该函数保留在堆栈上。func'func'MAKE_FUNCTION该指令使用一个参数(函数)调用函数(仍在堆栈上)。CALL_FUNCTIONdecoratefunc无论函数返回什么,都留在堆栈上,并由指令分配给名称。decoratefuncSTORE_NAME因此,如果函数没有返回任何内容,则不会为名称分配任何内容 - 甚至不会像语句中的原始函数那样。decoratorfuncdef
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python