Python 装饰器执行顺序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27342149/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 01:41:42  来源:igfitidea点击:

Decorator execution order

pythondecoratorpython-decorators

提问by Newbie

def make_bold(fn):
    return lambda : "<b>" + fn() + "</b>"

def make_italic(fn):
    return lambda : "<i>" + fn() + "</i>"

@make_bold
@make_italic
def hello():
  return "hello world"

helloHTML = hello()

Output: "<b><i>hello world</i></b>"

输出: "<b><i>hello world</i></b>"

I roughly understand about decorators and how it works with one of it in most examples.

我大致了解了装饰器以及它在大多数示例中如何与其中一个一起工作。

In this example, there are 2 of it. From the output, it seems that @make_italicexecutes first, then @make_bold.

在这个例子中,有 2 个。从输出来看,似乎@make_italic先执行,然后@make_bold.

Does this mean that for decorated functions, it will first run the function first then moving towards to the top for other decorators? Like @make_italicfirst then @make_bold, instead of the opposite.

这是否意味着对于装饰函数,它会首先运行该函数,然后移动到其他装饰器的顶部?像@make_italicfirst then @make_bold,而不是相反。

So this means that it is different from the norm of top-down approach in most programming lang? Just for this case of decorator? Or am I wrong?

所以这意味着它与大多数编程语言中自顶向下方法的规范不同?仅针对这种装饰器?还是我错了?

采纳答案by Martijn Pieters

Decorators wrapthe function they are decorating. So make_bolddecorated the result of the make_italicdecorator, which decorated the hellofunction.

装饰器包装他们正在装饰的函数。所以make_bold装饰了make_italic装饰器的结果,装饰器装饰了hello函数。

The @decoratorsyntax is really just syntactic sugar; the following:

@decorator语法真的只是语法糖; 下列:

@decorator
def decorated_function():
    # ...

is really executed as:

真正执行为:

def decorated_function():
    # ...
decorated_function = decorator(decorated_function)

replacing the original decorated_functionobject with whatever decorator()returned.

用返回的decorated_function任何内容替换原始对象decorator()

Stacking decorators repeats that process outward.

堆叠装饰器向外重复该过程。

So your sample:

所以你的样本:

@make_bold
@make_italic
def hello():
  return "hello world"

can be expanded to:

可以扩展为:

def hello():
  return "hello world"
hello = make_bold(make_italic(hello))

When you call hello()now, you are calling the object returned by make_bold(), really. make_bold()returned a lambdathat calls the function make_boldwrapped, which is the return value of make_italic(), which is also a lambda that calls the original hello(). Expanding all these calls you get:

当您hello()现在调用时make_bold(),实际上是在调用 返回的对象。make_bold()返回一个lambda调用被make_bold包装函数的a ,它是 的返回值make_italic(),它也是一个调用原始 的lambda hello()。扩展您获得的所有这些调用:

hello() = lambda : "<b>" + fn() + "</b>" #  where fn() ->
    lambda : "<i>" + fn() + "</i>" # where fn() -> 
        return "hello world"

so the output becomes:

所以输出变成:

"<b>" + ("<i>" + ("hello world") + "</i>") + "</b>"