2.1.2 修饰器

概述

这个令人惊讶功能在这门语言中出现几乎是有歉意的,并且担心它是否真的那么有用。

Bruce Eckel — Python修饰器简介

因为函数或类是对象,因此他们都可以传递。因为可以是可变的对象,所以他们可以被修改。函数或类对象被构建后,但是在绑定到他们的名称之前的修改行为被称为修饰。

在“修饰器”这个名称后面隐藏了两件事-一件是进行修饰工作(即进行真实的工作)的函数,另一件是遵守修饰器语法的表达式,[email protected]

用函数的修饰器语法可以修饰函数:

In [ ]:

  1. @decorator # ②
  2. def function(): # ①
  3. pass
  • 用标准形式定义的函数。①
  • [email protected]��[email protected],通常,这只是函数或类的名字。这部分首先被评估,在下面的函数定义完成后,修饰器被调用,同时将新定义的函数对象作为惟一的参数。修饰器的返回值被附加到函数的原始名称上。

修饰器可以被应用于函数和类。对于类,语法是一样的 - 原始类定义被作为一个参数来调用修饰器,并且无论返回什么都被赋给原始的名称。在修饰器语法实现之前(PEP 318),通过将函数或类对象赋给一个临时的变量,然后显性引用修饰器,然后将返回值赋给函数的名称,也可以到达相同的效果。这听起来像是打更多的字,确实是这样,并且被修饰函数的名字也被打了两次,因为临时变量必须被使用至少三次,这很容易出错。无论如何,上面的例子等同于:

In [ ]:

  1. def function(): # ①
  2. pass
  3. function = decorator(function) # ②

修饰器可以嵌套 - 应用的顺序是由底到顶或者由内到外。含义是最初定义的函数被第一个修饰器作为参数使用,第一个修饰器返回的内容被用于第二个修饰器的参数,…,最后一个修饰器返回的内容被绑定在最初的函数名称下。

选择这种修饰器语法是因为它的可读性。因为是在函数头之前指定的,很明显它并不是函数体的一部分,并且很显然它只能在整个函数上运行。因为,[email protected]("在你脸上",按照PEP的说法 :))。当使用多个修饰器时,每一个都是单独的一行,一种很容易阅读的方式。