Python装饰器深入解析:从基础到高级应用
·
Python装饰器深入解析:从基础到高级应用
引言
装饰器是Python中非常强大的特性,允许我们在不修改函数代码的情况下扩展其功能。作为从Python转向Rust的后端开发者,我发现装饰器是Python中最具特色的功能之一,广泛应用于日志记录、性能监控、权限验证等场景。本文将深入探讨装饰器的原理和最佳实践。
一、装饰器基础
1.1 什么是装饰器
装饰器是一种设计模式,用于包装函数或类,在不修改其源代码的情况下扩展功能。
def my_decorator(func):
def wrapper():
print("Before function")
func()
print("After function")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
1.2 装饰器语法
# 装饰器应用
@decorator
def function():
pass
# 等价于
function = decorator(function)
1.3 带参数的装饰器
def repeat(times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(times=3)
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
二、高级装饰器
2.1 保留函数元数据
import functools
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@my_decorator
def example():
"""This is a docstring"""
pass
print(example.__name__) # example
print(example.__doc__) # This is a docstring
2.2 类装饰器
class CountCalls:
def __init__(self, func):
self.func = func
self.count = 0
def __call__(self, *args, **kwargs):
self.count += 1
print(f"Call {self.count} of {self.func.__name__}")
return self.func(*args, **kwargs)
@CountCalls
def say_hello():
print("Hello!")
say_hello() # Call 1 of say_hello; Hello!
say_hello() # Call 2 of say_hello; Hello!
2.3 多个装饰器
def decorator1(func):
def wrapper(*args, **kwargs):
print("Decorator 1 before")
result = func(*args, **kwargs)
print("Decorator 1 after")
return result
return wrapper
def decorator2(func):
def wrapper(*args, **kwargs):
print("Decorator 2 before")
result = func(*args, **kwargs)
print("Decorator 2 after")
return result
return wrapper
@decorator1
@decorator2
def greet():
print("Hello!")
# 执行顺序:decorator1(decorator2(greet))
greet()
三、装饰器实战
3.1 日志记录
import logging
logging.basicConfig(level=logging.INFO)
def log_function(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
logging.info(f"Calling {func.__name__} with args: {args}, kwargs: {kwargs}")
try:
result = func(*args, **kwargs)
logging.info(f"{func.__name__} returned: {result}")
return result
except Exception as e:
logging.error(f"{func.__name__} raised {type(e).__name__}: {e}")
raise
return wrapper
@log_function
def add(a, b):
return a + b
3.2 性能监控
import time
def timeit(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
elapsed = time.time() - start
print(f"{func.__name__} took {elapsed:.4f} seconds")
return result
return wrapper
@timeit
def slow_function():
time.sleep(1)
return "Done"
3.3 权限验证
def require_permission(permission):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
current_user = get_current_user()
if permission not in current_user.permissions:
raise PermissionError(f"Permission {permission} required")
return func(*args, **kwargs)
return wrapper
return decorator
@require_permission('admin')
def delete_user(user_id):
# 删除用户逻辑
pass
四、装饰器设计模式
4.1 工厂模式
def create_validator(validation_func):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
if not validation_func(*args, **kwargs):
raise ValueError("Validation failed")
return func(*args, **kwargs)
return wrapper
return decorator
def is_positive(*args):
return all(arg > 0 for arg in args)
@create_validator(is_positive)
def divide(a, b):
return a / b
4.2 观察者模式
def event_handler(event_name):
def decorator(func):
register_event_handler(event_name, func)
return func
return decorator
@event_handler('user_created')
def send_welcome_email(user):
print(f"Sending welcome email to {user.email}")
4.3 策略模式
def strategy(name):
def decorator(func):
register_strategy(name, func)
return func
return decorator
@strategy('quick_sort')
def quick_sort(arr):
# 快速排序实现
pass
@strategy('merge_sort')
def merge_sort(arr):
# 归并排序实现
pass
五、装饰器最佳实践
5.1 保持装饰器简洁
# 不好:装饰器过于复杂
def complex_decorator(func):
def wrapper(*args, **kwargs):
# 大量逻辑...
if condition1:
# 处理...
elif condition2:
# 处理...
return func(*args, **kwargs)
return wrapper
# 好:将逻辑分离到单独函数
def validate_input(args):
# 验证逻辑
pass
def log_call(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
validate_input(args)
return func(*args, **kwargs)
return wrapper
5.2 使用类装饰器管理状态
class Cached:
def __init__(self, func):
self.func = func
self.cache = {}
def __call__(self, *args):
if args not in self.cache:
self.cache[args] = self.func(*args)
return self.cache[args]
@Cached
def expensive_computation(n):
# 耗时计算
return n * n
5.3 避免过度使用装饰器
# 不好:装饰器过多难以理解
@decorator1
@decorator2
@decorator3
@decorator4
def my_function():
pass
# 好:合并相关装饰器
def combined_decorator(func):
return decorator1(decorator2(decorator3(func)))
@combined_decorator
def my_function():
pass
六、内置装饰器
6.1 @staticmethod
class MyClass:
@staticmethod
def helper():
return "Helper method"
# 不需要实例化
MyClass.helper()
6.2 @classmethod
class MyClass:
instance_count = 0
def __init__(self):
MyClass.instance_count += 1
@classmethod
def get_instance_count(cls):
return cls.instance_count
6.3 @property
class Person:
def __init__(self, name):
self._name = name
@property
def name(self):
return self._name
@name.setter
def name(self, value):
if not value:
raise ValueError("Name cannot be empty")
self._name = value
七、总结
装饰器是Python中非常强大的特性,通过合理使用可以提高代码的可读性和可维护性。
关键要点:
- 使用functools.wraps:保留函数元数据
- 保持装饰器简洁:避免过于复杂的逻辑
- 类装饰器:适合需要管理状态的场景
- 组合装饰器:合并相关功能
- 内置装饰器:staticmethod、classmethod、property
从Python转向Rust后,我发现Rust的宏系统可以实现类似装饰器的功能,但语法和使用方式有所不同。
延伸阅读
- Python装饰器官方文档
- functools模块文档
- 《Python Cookbook》装饰器章节
- Python装饰器设计模式
更多推荐



所有评论(0)