文章目录
Python中的 装饰器(decorator) 是一种用于修改函数或类行为的函数。它们允许我们在不修改原函数的情况下,动态地增加功能,通常用于日志记录、性能测试、权限验证等。装饰器本质上是高阶函数,即接受一个函数作为参数并返回一个新的函数。
装饰器的基本原理
装饰器本质上是一个闭包(closure),它将目标函数包裹在一个函数内部,然后通过调用装饰器返回的函数来执行新的行为。通过这种方式,我们可以在不改变目标函数的情况下增强其功能。
最简单的装饰器例子
def my_decorator(func):
def wrapper():
print("在函数执行之前做一些事情")
func()
print("在函数执行之后做一些事情")
return wrapper
# 使用装饰器
@my_decorator
def say_hello():
print("Hello, World!")
say_hello()
输出:
在函数执行之前做一些事情
Hello, World!
在函数执行之后做一些事情
原理分析
my_decorator
是一个装饰器,它接受一个函数func
作为参数。wrapper
是内部定义的函数,负责在目标函数前后添加额外的逻辑。- 使用
@my_decorator
语法糖相当于say_hello = my_decorator(say_hello)
,即say_hello
现在指向wrapper
函数。 - 当
say_hello()
被调用时,实际执行的是wrapper()
函数,它在目标函数say_hello()
前后插入了额外的逻辑。
带参数的装饰器
有时我们希望装饰器能够接受额外的参数,比如记录日志时可以指定日志级别,这时我们可以让装饰器函数接受参数。
带参数的装饰器例子
def my_decorator_with_args(message):
def decorator(func):
def wrapper(*args, **kwargs):
print(f"装饰器参数:{message}")
return func(*args, **kwargs)
return wrapper
return decorator
# 使用装饰器,传递参数
@my_decorator_with_args("这是一个装饰器参数")
def say_hello(name):
print(f"Hello, {name}!")
say_hello("Alice")
输出:
装饰器参数:这是一个装饰器参数
Hello, Alice!
原理分析
my_decorator_with_args
接受参数message
并返回一个装饰器函数decorator
。decorator
接受目标函数func
并返回一个包装函数wrapper
,该包装函数在执行目标函数之前输出装饰器参数。@my_decorator_with_args("这是一个装饰器参数")
是通过传参的方式动态生成装饰器,并应用到say_hello
上。
通用装饰器
装饰器经常需要应用于带有参数的函数,Python 提供了 *args
和 **kwargs
来捕获任意数量的位置和关键字参数,以便装饰器通用性更强。
示例:处理带有参数的函数
def my_decorator(func):
def wrapper(*args, **kwargs):
print("函数执行之前")
result = func(*args, **kwargs)
print("函数执行之后")
return result
return wrapper
@my_decorator
def add(a, b):
return a + b
result = add(3, 5)
print(f"结果是: {result}")
输出:
函数执行之前
函数执行之后
结果是: 8
Python内置装饰器
Python 提供了几个内置的装饰器,最常见的包括:
@property
:将类方法转化为属性。@staticmethod
:将类方法变为静态方法,不需要self
参数。@classmethod
:将类方法的第一个参数变为类本身 (cls
),而不是实例。
@property
示例
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, value):
if value <= 0:
raise ValueError("半径必须大于0")
self._radius = value
circle = Circle(5)
print(circle.radius) # 使用属性
circle.radius = 10 # 设置新值
print(circle.radius)
输出:
5
10
装饰器的嵌套(多个装饰器)
多个装饰器可以通过多个 @
来嵌套使用,装饰器的执行顺序是从内向外的。
示例
def decorator1(func):
def wrapper(*args, **kwargs):
print("执行decorator1")
return func(*args, **kwargs)
return wrapper
def decorator2(func):
def wrapper(*args, **kwargs):
print("执行decorator2")
return func(*args, **kwargs)
return wrapper
@decorator1
@decorator2
def greet(name):
print(f"Hello, {name}!")
greet("Bob")
输出:
执行decorator1
执行decorator2
Hello, Bob!
总结
- 装饰器 是修改函数或类行为的一种简洁方式,允许你在不改变原代码的情况下增强功能。
- 装饰器可以通过
@
来简化代码,并且支持传递参数和嵌套。 - Python 中有许多内置装饰器,如
@property
、@staticmethod
和@classmethod
,让类的定义更为灵活。