在Python中,函数装饰器(decorator)是一种用于修改或扩展函数行为的高级特性。装饰器本质上是一个函数,它接收另一个函数作为参数,并返回一个新的函数或可调用对象。装饰器的主要作用包括:
- 代码重用: 将通用功能提取到装饰器中,避免重复代码;
- 功能增强: 在不修改函数源代码的前提下,增强函数的功能;
- 分离关注点: 将辅助功能(如日志、验证)与业务逻辑分离,代码更加清晰易读。
1.基本语法
装饰器通常通过在函数定义前使用@decorator_name
语法来应用,例如
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Something is happening before the function is called.")
result = func(*args, **kwargs)
print("Something is happening after the function is called.")
return result
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
上述代码的输出为
Something is happening before the function is called.
Hello!
Something is happening after the function is called.
那么上述代码的实现流程是什么呢,是怎样做到这样的输出的呢?
2.执行过程
当调用一个使用装饰器的函数时,程序的执行过程如下:
-
定义阶段: 装饰器被应用于函数时,会首先执行装饰器函数,并将目标函数作为参数传递给装饰器函数。装饰器函数返回一个新的函数(通常是一个内部定义的
wrapper
函数)来取代原始函数。 -
调用阶段: 当调用被装饰的函数时,实际上调用的是装饰器返回的
wrapper
函数。
具体执行过程可以通过一个例子详细说明:
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Something is happening before the function is called.")
result = func(*args, **kwargs)
print("Something is happening after the function is called.")
return result
return wrapper
@my_decorator
def say_hello():
print("Hello!")
在这个例子中,定义阶段为
@my_decorator
def say_hello():
print("Hello!")
上述代码等同于
def say_hello():
print("Hello!")
say_hello = my_decorator(say_hello)
my_decorator
函数接收say_hello
函数作为参数;-
my_decorator
函数内部定义了一个新的函数wrapper;
my_decorator
返回wrapper
函数,并将其赋值给say_hello。
而调用阶段
say_hello()
当调用say_hello()
时,实际调用的是装饰器返回的wrapper
函数,执行的也是wrapper()
def wrapper(*args, **kwargs):
print("Something is happening before the function is called.")
result = func(*args, **kwargs) # 这里的 func 是原始的 say_hello 函数
print("Something is happening after the function is called.")
return result
wrapper
函数先打印"Something is happening before the function is called.";wrapper
函数调用原始的say_hello
函数,输出"Hello!";wrapper
函数打印"Something is happening after the function is called.";wrapper
函数返回原始函数的返回值(如果有的话)。
执行过程总结
定义阶段:
- 装饰器
my_decorator
被应用,返回wrapper
函数。 say_hello
被赋值为wrapper
函数。
调用阶段:
- 调用
say_hello()
实际上是调用wrapper()
。 wrapper
执行,先打印"Something is happening before the function is called."。wrapper
调用原始的say_hello
函数,打印"Hello!"。wrapper
打印"Something is happening after the function is called."。wrapper
返回结果。
通过这种方式,装饰器可以在不改变原始函数代码的情况下,添加或修改函数的行为。