python装饰器可分为函数装饰器和类装饰器,在理解过程中,可以认为是相同的。
一、不带参数的函数装饰器
def my_decorator(func):
def wrapper():
print("函数执行前")
func()
print("函数执行后")
return wrapper
这里my_decorator就是我们定义的一个不带参数的装饰器(其本身就是一个函数),
使用如下:
@my_decorator
def say_hello():
print("Hello!")
上述代码段可以简单的理解为say_hello=my_decorator(say_hello)
,即将say_hello函数作为参数传递给装饰器函数,并返回装饰器函数中定义的函数名。因此,say_hello=wrapper
。
当我们执行say_hello()
时,相当于执行wrapper()
。
执行结果如下:
say_hello()
输出:
复制函数执行前
Hello!
函数执行后
二、带参数的函数装饰器
定义带参数的函数装饰器
def repeat(num_times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
使用如下:
@repeat(3)
def greet(name):
print(f"Hello, {name}!")
这里,@repeat(3)
相当于@decorator
(可以简单的理解为,先将参数传递给外部装饰器repeat,然后返回真正的装饰器decorator)
因此 上述代码可以看做greet=decorator(greet)
,greet = wrapper
只是相比于不带参数的装饰器多传递了一个参数。
当我们执行greet()
时,同样相当于执行wrapper()
。
执行实例如下:
greet("Alice")
输出:
Hello, Alice!
Hello, Alice!
Hello, Alice!
三、类装饰器
定义类装饰器
class MyDecorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print("函数执行前")
result = self.func(*args, **kwargs)
print("函数执行后")
return result
调用如下:
@MyDecorator
def say_hello():
print("Hello!")
上述代码可以直接理解为say_hello = MyDecorator(say_hello)
因此,当使用say_hello()
时,相当于直接调用__call__()
函数
执行实例如下:
say_hello()
输出:
函数执行前
Hello!
函数执行后
四、装饰器作用于类定义
定义装饰器:
def add_class_name(cls):
# 在类上添加一个属性,并返回原类
cls.class_name = 'person class'
return cls
调用如下:
@add_class_name
class Person:
def __init__(self, name):
self.name = name
上述代码可以等价于Person = add_class_name(Person)
,那么此时调用Person就相当于调用add_class_name(Person)
执行实例
A = Person()
上面这行代码相当于在运行A = add_class_name( Person)
运行的结果,就是返回了一个被装饰过的新的cls,因此新的cls有了新的属性class_name
,我们就可以调用 print(A.class_name) # 输出: "person class"
五、 装饰器的作用
个人理解:
- 增加代码复用:装饰器中封装一些通用的功能,定义不同函数时都可以利用装饰器中的功能。(固定装饰器,原函数不固定);
- 为原函数拓展功能:不改动原函数中的代码,例如:第一节中的
say_hello()
函数作为无法改动的原函数,那么我们可以通过改动装饰器中的功能,为原函数添加拓展功能(固定原函数,改动装饰器);
六、应用场景
Python 中装饰器的应用场景主要用于代码复用、逻辑抽离和横切关注点(如日志、验证、缓存、安全控制等)。下面是一些典型应用场景和具体示例:
6.1 日志记录(Logging)
用途:记录函数或方法的调用行为,便于调试和分析。
def log(func):
def wrapper(*args, **kwargs):
print(f"[LOG] Calling {func.__name__} with args={args}, kwargs={kwargs}")
result = func(*args, **kwargs)
print(f"[LOG] {func.__name__} returned {result}")
return result
return wrapper
@log
def add(a, b):
return a + b
add(2, 3)
6.2. 权限验证(Authentication/Authorization)
用途:用于 Web 应用、命令行工具中限制某些函数的访问。
def require_admin(func):
def wrapper(user, *args, **kwargs):
if not user.get("is_admin"):
raise PermissionError("You must be an admin.")
return func(user, *args, **kwargs)
return wrapper
@require_admin
def delete_user(user, user_id):
print(f"Deleting user {user_id}")
6.3. 函数缓存(Memoization)
用途:缓存计算结果,加速函数响应,避免重复计算。
from functools import lru_cache
@lru_cache(maxsize=128)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(40)) # 快速返回
6.4. 性能计时(Profiling)
用途:度量函数执行时间,用于性能分析。
import time
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took {end - start:.4f}s")
return res
return wrapper
@timer
def slow_function():
time.sleep(1)
return "Done"
slow_function()
6.5. 类注册与插件机制
用途:动态注册类或函数用于工厂、插件系统。
registry = {}
def register(name):
def decorator(cls):
registry[name] = cls
return cls
return decorator
@register("dog")
class Dog:
def speak(self):
return "Woof"
print(registry["dog"]().speak()) # 输出 "Woof"
6.6. 输入验证 / 参数检查
用途:自动检查输入是否符合预期。
def validate_non_negative(func):
def wrapper(x):
if x < 0:
raise ValueError("Negative value not allowed")
return func(x)
return wrapper
@validate_non_negative
def sqrt(x):
return x ** 0.5
6.7. 类装饰器(用于元编程、修改类行为)
用途:为类增加静态属性、方法、注册机制等。
def add_repr(cls):
def __repr__(self):
return f"{cls.__name__}({self.__dict__})"
cls.__repr__ = __repr__
return cls
@add_repr
class Person:
def __init__(self, name):
self.name = name
print(Person("Alice"))