python装饰器会立即调用返回的回调吗?

提问

我正在尝试通过一些实验来了解装饰器的行为.我找不到所见内容的任何文档,因此可能有人可以将我指向某些内容.

这是使用装饰器的代码:

def register():
    def func_wrapper(func):
        print 'registered'
    return func_wrapper

@register()
def main_page_func():
    pass

运行此代码时,将显示“注册”一词:

registered

这大概是没有装饰器的等效代码(?):

def register(func):
    def func_wrapper():
        print 'registered'
    return func_wrapper


def main_page_func():
    pass

main_page_func = register(main_page_func)

当您执行上述操作时,什么都不会打印出来.我了解这种情况:func_wrapper回调返回.

但是,我仍然在使用装饰器的第一种情况下苦苦挣扎:鉴于main_page_func从未被调用,为什么要调用print语句?

谢谢.

最佳答案

当你说,

@register()

它实际上调用了函数register(),并在那里使用了返回值,它将是func_wrapper,它接受一个函数对象作为输入.所以,你要做的是

@func_wrapper
def main_page_func():
    pass

当你这样装饰它时,

main_page_func = func_wrapper(main_page_func)

func_wrapper被调用,这就是为什么注册被打印的原因.

要真正解决此问题,您需要传递函数对象进行注册,例如在第二个示例中,

def register(func):         # func should be here
    def func_wrapper():     # not here
        print 'registered'
    return func_wrapper


@register                   # no parens after `register`
def main_page_func():
    pass

现在,评估是这样的

main_page_func = register(main_page_func)

由于func_wrapper尚未执行,因此您将不会看到已注册的打印内容.