Python 中的修饰器(decorator)是一个函数,它接受一个函数或方法作为其唯一的参数,并返回一个新的函数或方法,其中整合了修饰后的函数或方法,以及附带的一些额外功能。 简单来说,修饰器可以在不修改被修饰函数原有代码的情况下,为其添加额外的功能。例如用于性能分析、日志记录、权限控制、缓存、参数验证、事务处理、重试机制、异常处理等。
实现原理
装饰器的实现原理基于 Python 的函数对象和闭包的概念。
在 Python 中,函数是“一等公民”,这意味着函数可以像其他对象一样被传递、赋值和返回。
当使用装饰器时,例如 @decorator 应用于一个函数
func ,实际上发生了以下过程:
- 定义装饰器函数
decorator,它接受一个函数作为参数。 - 当解释器遇到
@decorator应用于func时,它会将func作为参数传递给decorator。 decorator内部通常会定义一个新的函数(比如wrapper),在这个新函数中,会执行一些额外的操作(例如在函数执行前后添加代码),然后调用被装饰的函数func。- 最后,
decorator返回这个新定义的函数wrapper。 - 后续对
func的调用实际上是在调用装饰器返回的wrapper函数,从而实现了在不修改原始函数代码的情况下,为函数添加了额外的功能。
这种机制利用了函数可以作为参数传递和返回,以及在函数内部可以定义新函数并形成闭包(即新函数可以访问外部函数的变量)的特性。
比如: 1
2
3
4
5
6
7
8
9
10
11
12def my_decorator(func):
def wrapper():
print("Before function execution")
func()
print("After function execution")
return wrapper
def my_function():
print("Inside my_function")
my_function()
在这个例子中,my_decorator
就是一个装饰器函数,它返回了一个新的函数 wrapper ,当调用
my_function 时,实际上是在调用 wrapper
,从而实现了在 my_function 执行前后打印额外信息的功能。
Timeit 修饰器
正常使用 time 库来测试方法的性能的时候,通常需要写很多代码,而且几乎都是重复的. 这里创建 timeit 修饰器的话,可以在被测试的方法上直接添加修饰器使用,使用起来更方便而且还能减少代码量.
1 | """根据上面的实现原理,我们可以实现一个 timeit 修饰器,使用的时候可以直接在方法前加 @timeit 就可以查看方法运行时间了.""" |
这里需要注意的是, 方法
wrapper的命名不是强制的, 把名字改为wrapper2的话该修饰器一样有效.