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
Decorator execution order
提问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_italic
executes 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_italic
first then @make_bold
, instead of the opposite.
这是否意味着对于装饰函数,它会首先运行该函数,然后移动到其他装饰器的顶部?像@make_italic
first 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_bold
decorated the result of the make_italic
decorator, which decorated the hello
function.
装饰器包装他们正在装饰的函数。所以make_bold
装饰了make_italic
装饰器的结果,装饰器装饰了hello
函数。
The @decorator
syntax 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_function
object 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 lambda
that calls the function make_bold
wrapped, 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>"