Python装饰器深入解析:从基础到高级
Python装饰器深入解析从基础到高级引言装饰器是Python中最强大的特性之一它允许我们在不修改函数代码的情况下增强函数的功能。作为一名从Python转向Rust的后端开发者我在实践中总结了装饰器的最佳实践。本文将深入探讨Python装饰器的原理和高级用法帮助你掌握这一核心技术。一、装饰器基础概念1.1 什么是装饰器装饰器是一种设计模式用于在不修改原函数代码的情况下为函数添加额外的功能。1.2 装饰器的作用日志记录记录函数调用信息性能统计计算函数执行时间权限控制验证用户权限缓存缓存函数返回结果输入验证验证函数参数1.3 装饰器的语法decorator def function(): pass等价于def function(): pass function decorator(function)二、基础装饰器实现2.1 简单装饰器def simple_decorator(func): def wrapper(): print(Before function call) func() print(After function call) return wrapper simple_decorator def say_hello(): print(Hello!) say_hello()2.2 带参数的装饰器def greeting_decorator(greeting): def decorator(func): def wrapper(*args, **kwargs): print(f{greeting}!) return func(*args, **kwargs) return wrapper return decorator greeting_decorator(Good morning) def say_hello(name): print(fHello, {name}!) say_hello(Alice)2.3 保留函数元信息import functools def preserve_metadata(func): functools.wraps(func) def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper preserve_metadata def my_function(): This is a docstring pass print(my_function.__name__) print(my_function.__doc__)三、装饰器进阶3.1 类装饰器class DecoratorClass: def __init__(self, func): self.func func def __call__(self, *args, **kwargs): print(Before) result self.func(*args, **kwargs) print(After) return result DecoratorClass def add(a, b): return a b print(add(2, 3))3.2 带参数的类装饰器class ParametrizedDecorator: def __init__(self, prefix): self.prefix prefix def __call__(self, func): functools.wraps(func) def wrapper(*args, **kwargs): result func(*args, **kwargs) return f{self.prefix}{result} return wrapper ParametrizedDecorator(prefixResult: ) def multiply(a, b): return a * b print(multiply(4, 5))3.3 装饰器堆叠def bold(func): functools.wraps(func) def wrapper(): return fb{func()}/b return wrapper def italic(func): functools.wraps(func) def wrapper(): return fi{func()}/i return wrapper bold italic def greet(): return Hello print(greet())四、实用装饰器案例4.1 日志装饰器import logging logging.basicConfig(levellogging.INFO) def log_decorator(func): functools.wraps(func) def wrapper(*args, **kwargs): logging.info(fCalling {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_decorator def divide(a, b): return a / b divide(10, 2) divide(10, 0)4.2 性能统计装饰器import time def timeit(func): functools.wraps(func) def wrapper(*args, **kwargs): start time.time() result func(*args, **kwargs) end time.time() print(f{func.__name__} executed in {end - start:.4f} seconds) return result return wrapper timeit def slow_function(): time.sleep(2) return Done slow_function()4.3 缓存装饰器def memoize(func): cache {} functools.wraps(func) def wrapper(*args): if args not in cache: cache[args] func(*args) return cache[args] return wrapper memoize def fibonacci(n): if n 1: return n return fibonacci(n - 1) fibonacci(n - 2) print(fibonacci(40))4.4 权限验证装饰器def require_permission(permission): def decorator(func): functools.wraps(func) def wrapper(user, *args, **kwargs): if permission not in user.get(permissions, []): raise PermissionError(fUser lacks {permission} permission) return func(user, *args, **kwargs) return wrapper return decorator require_permission(admin) def delete_user(user, user_id): print(fUser {user[name]} deleted user {user_id}) admin_user {name: Admin, permissions: [admin]} normal_user {name: User, permissions: [read]} delete_user(admin_user, 1) delete_user(normal_user, 1)五、内置装饰器5.1 staticmethodclass MyClass: staticmethod def static_method(): print(This is a static method) MyClass.static_method()5.2 classmethodclass MyClass: instance_count 0 def __init__(self): MyClass.instance_count 1 classmethod def get_instance_count(cls): return cls.instance_count obj1 MyClass() obj2 MyClass() print(MyClass.get_instance_count())5.3 propertyclass Person: def __init__(self, name): self._name name property def name(self): return self._name name.setter def name(self, value): if not isinstance(value, str): raise TypeError(Name must be a string) self._name value p Person(Alice) print(p.name) p.name Bob六、装饰器最佳实践6.1 使用functools.wrapsdef my_decorator(func): functools.wraps(func) def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper6.2 装饰器文档化def my_decorator(func): Decorator that does something functools.wraps(func) def wrapper(*args, **kwargs): Wrapper function return func(*args, **kwargs) return wrapper6.3 装饰器组合def compose(*decorators): def apply_decorators(func): for decorator in reversed(decorators): func decorator(func) return func return apply_decorators compose(log_decorator, timeit) def my_function(): pass七、实战案例完整的装饰器系统import functools import logging import time from typing import Callable, Any logging.basicConfig(levellogging.INFO) def log(func: Callable[..., Any]) - Callable[..., Any]: functools.wraps(func) def wrapper(*args: Any, **kwargs: Any) - Any: logging.info(fCalling {func.__name__}) return func(*args, **kwargs) return wrapper def timeit(func: Callable[..., Any]) - Callable[..., Any]: functools.wraps(func) def wrapper(*args: Any, **kwargs: Any) - Any: start time.time() result func(*args, **kwargs) end time.time() logging.info(f{func.__name__} took {end - start:.2f}s) return result return wrapper def validate_types(**type_map: type) - Callable[[Callable[..., Any]], Callable[..., Any]]: def decorator(func: Callable[..., Any]) - Callable[..., Any]: functools.wraps(func) def wrapper(*args: Any, **kwargs: Any) - Any: for arg_name, expected_type in type_map.items(): if arg_name in kwargs: if not isinstance(kwargs[arg_name], expected_type): raise TypeError(f{arg_name} must be {expected_type}) return func(*args, **kwargs) return wrapper return decorator log timeit validate_types(aint, bint) def process_data(a: int, b: int) - int: Process data and return result time.sleep(0.5) return a b result process_data(a10, b20) print(fResult: {result})总结装饰器是Python中非常强大的特性通过本文的学习你应该掌握了以下核心要点装饰器基础定义、语法、作用基础实现简单装饰器、带参数装饰器类装饰器使用类实现装饰器装饰器堆叠多个装饰器组合使用实用案例日志、性能统计、缓存、权限验证内置装饰器staticmethod、classmethod、property最佳实践保留元信息、文档化、组合装饰器作为从Python转向Rust的后端开发者掌握装饰器对于编写优雅、可维护的代码至关重要。虽然Rust没有直接的装饰器语法但可以通过宏和trait实现类似的功能。