小编典典

装饰器执行顺序

python

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

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

我大致了解装饰器,以及在大多数示例中它如何与装饰器一起使用。

在此示例中,有2个。从输出看,似乎@make_italic先执行,然后执行@make_bold

这是否意味着对于装饰功能,它将首先运行该功能,然后移至其他装饰器的顶部?像@make_italic先那么@make_bold,而不是相反。

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


阅读 182

收藏
2020-12-20

共1个答案

小编典典

装饰器 包装 正在装饰的功能。这样就make_bold修饰了make_italic装饰器的结果,从而修饰了hello功能。

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

@decorator
def decorated_function():
    # ...

实际执行为:

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

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

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

因此,您的示例:

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

可以扩展为:

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

当你打电话hello()了,你调用返回的对象make_bold(),真的。make_bold()返回一个lambda,调用make_bold包装的函数,这是的返回值make_italic(),它也是一个调用原始函数的lambda
hello()。扩展所有这些调用,您将得到:

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

因此输出变为:

"<b>" + ("<i>" + ("hello world") + "</i>") + "</b>"
2020-12-20