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
的话该修饰器一样有效.