python - 装饰器执行顺序

标签 python decorator python-decorators

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 ,而不是相反。

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

最佳答案

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

@decorator 语法实际上只是语法糖;以下:

@decorator
def decorated_function():
    # ...

实际上是这样执行的:

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

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

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

所以你的样本:

@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()返回一个调用make_bold函数封装的lambda,也就是make_italic()的返回值,它也是一个调用原始 hello() 的 lambda。扩展您收到的所有这些电话:

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

所以输出变成:

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

关于python - 装饰器执行顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27342149/

相关文章:

python - 在 R 和 pandas 中合并并保持顺序

python - 有没有办法通过 Airflow API 创建/修改连接

python - 如何扩展 functools.wraps 装饰器的功能?

c++ - 可组合的 C++ 函数装饰器

python - 装饰后不再获取函数的返回值

pytest - 如何将测试标记为 "long"并跳过它们?

python - 让子进程正确格式化

没有 Oracle 客户端的 Python Oracle DB Connect

python - 在同一类的方法中使用类/静态方法作为默认参数值

python-2.7 - 如何将关键字参数添加到 Python 2.7 中的包装函数?