元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
Python基础语法
Python环境安装与配置
第一个Python程序
变量与数据类型
字面量详解
基本运算符
流程控制语句
包管理与虚拟环境
▶
Python数据结构
列表(List)详解
元组(Tuple)使用指南
字典(Dict)完全解析
集合(Set)操作大全
▶
函数与模块
函数定义与参数传递
Lambda表达式
模块导入与使用
常用内置函数
▶
面向对象编程
类与对象
继承与多态
魔术方法解析
装饰器原理与应用
▶
Python类型系统
类型注解(Type Hints)
Pydantic基础
Pydantic高级特性
typing模块基础
泛型类型详解
泛型类详解
Callable类型详解
Awaitable类型详解
类型变量与约束
类型别名与Protocol
TypedDict详解
Annotated类型
Reducer类型
类型检查工具使用
类型注解最佳实践
▶
关键字
pass关键字
raise关键字
global关键字
nonlocal关键字
yield关键字
assert关键字
with关键字
async/await关键字
▶
包管理
pip包管理基础
虚拟环境管理
包管理工具对比
requirements.txt规范
依赖管理与requirements.txt
setup.py配置说明
Poetry项目管理工具
Conda包管理系统
打包与发布Python包
PyPI发布流程
私有PyPI仓库
▶
Python高级特性
迭代器与生成器
多线程编程
协程与异步IO
元编程入门
反射机制详解
描述符协议
上下文管理器协议
垃圾回收机制
内存管理深度解析
性能优化指南
▶
文件与异常处理
文件读写操作
JSON数据解析
异常处理机制
上下文管理器
发布时间:
2025-03-24 13:20
↑
☰
# Python装饰器原理与应用 本文将详细介绍Python中的装饰器(Decorator)概念,帮助你深入理解装饰器的工作原理及其在实际编程中的应用。 ## 装饰器基础 装饰器是Python中的一个重要特性,它允许我们修改函数或类的行为而不直接改变其源代码。装饰器本质上是一个函数,它接受一个函数作为参数并返回一个新的函数。 ### 基本语法 ```python def my_decorator(func): def wrapper(): print("Something is happening before the function is called.") func() print("Something is happening after the function is called.") 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. ``` ### 带参数的装饰器 ```python 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(3) def greet(name): print(f"Hello {name}!") greet("Alice") # 输出: # Hello Alice! # Hello Alice! # Hello Alice! ``` ## 装饰器工作原理 ### 函数作为对象 在Python中,函数是一等公民,这意味着函数可以: - 赋值给变量 - 作为参数传递 - 作为返回值返回 ```python def greet(name): return f"Hello, {name}!" # 将函数赋值给变量 say_hello = greet # 调用函数 print(say_hello("Bob")) # Hello, Bob! ``` ### 闭包 闭包是装饰器实现的关键概念: ```python def outer_function(x): def inner_function(y): return x + y return inner_function # 创建一个闭包 add_five = outer_function(5) print(add_five(3)) # 8 ``` ### 装饰器执行顺序 ```python def bold(func): def wrapper(): return "<b>" + func() + "</b>" return wrapper def italic(func): def wrapper(): return "<i>" + func() + "</i>" return wrapper @bold @italic def hello(): return "Hello, World!" print(hello()) # <b><i>Hello, World!</i></b> ``` ## 常用装饰器模式 ### 1. 函数执行时间计算 ```python import time import functools def timer(func): @functools.wraps(func) def wrapper(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) end_time = time.time() print(f"{func.__name__} took {end_time - start_time:.2f} seconds to execute") return result return wrapper @timer def slow_function(): time.sleep(1) return "Function completed" slow_function() ``` ### 2. 缓存装饰器 ```python 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 < 2: return n return fibonacci(n-1) + fibonacci(n-2) print(fibonacci(10)) # 快速计算,因为中间结果被缓存 ``` ### 3. 参数验证装饰器 ```python def validate_types(*types): def decorator(func): @functools.wraps(func) def wrapper(*args): if len(args) != len(types): raise ValueError("参数数量不匹配") for arg, type_ in zip(args, types): if not isinstance(arg, type_): raise TypeError(f"参数类型错误: 期望 {type_}, 得到 {type(arg)}") return func(*args) return wrapper return decorator @validate_types(int, int) def add_numbers(x, y): return x + y print(add_numbers(1, 2)) # 3 # print(add_numbers(1, "2")) # 抛出TypeError ``` ## 类装饰器 类装饰器可以用来修改类的行为: ```python def singleton(cls): instances = {} @functools.wraps(cls) def get_instance(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return get_instance @singleton class Database: def __init__(self): print("Initializing database connection") # 创建多个实例实际上会返回同一个实例 db1 = Database() db2 = Database() # 不会打印初始化消息 print(db1 is db2) # True ``` ## 实际应用示例 ### 1. API访问控制 ```python from functools import wraps from time import time def rate_limit(max_calls, time_frame): calls = [] def decorator(func): @wraps(func) def wrapper(*args, **kwargs): now = time() # 移除超过时间框架的调用记录 calls[:] = [call for call in calls if call > now - time_frame] if len(calls) >= max_calls: raise Exception(f"超过访问限制: {max_calls}次/{time_frame}秒") calls.append(now) return func(*args, **kwargs) return wrapper return decorator @rate_limit(max_calls=2, time_frame=10) def api_request(): return "API response" # 测试 print(api_request()) # 正常调用 print(api_request()) # 正常调用 # print(api_request()) # 抛出异常 ``` ### 2. 日志记录 ```python import logging from functools import wraps logging.basicConfig(level=logging.INFO) def log_function_call(func): @wraps(func) def wrapper(*args, **kwargs): args_repr = [repr(a) for a in args] kwargs_repr = [f"{k}={v!r}" for k, v in kwargs.items()] signature = ", ".join(args_repr + kwargs_repr) logging.info(f"调用函数 {func.__name__}({signature})") try: result = func(*args, **kwargs) logging.info(f"{func.__name__} 返回值: {result!r}") return result except Exception as e: logging.error(f"{func.__name__} 抛出异常: {str(e)}") raise return wrapper @log_function_call def divide(x, y): return x / y # 测试 divide(10, 2) # 正常调用,记录日志 # divide(10, 0) # 异常调用,记录错误 ``` ### 3. 权限控制 ```python from functools import wraps def require_permission(permission): def decorator(func): @wraps(func) def wrapper(user, *args, **kwargs): if permission not in user.permissions: raise PermissionError( f"用户 {user.username} 没有 {permission} 权限" ) return func(user, *args, **kwargs) return wrapper return decorator class User: def __init__(self, username, permissions): self.username = username self.permissions = permissions class Document: @require_permission("edit_document") def edit(self, user, content): print(f"{user.username} 编辑文档: {content}") # 测试 user1 = User("admin", ["edit_document", "delete_document"]) user2 = User("guest", ["view_document"]) doc = Document() doc.edit(user1, "Hello") # 正常编辑 # doc.edit(user2, "Hello") # 抛出权限错误 ``` ## 最佳实践 1. **使用functools.wraps** ```python # 不好的做法 def my_decorator(func): def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper # 好的做法 from functools import wraps def my_decorator(func): @wraps(func) def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper ``` 2. **保持装饰器简单** ```python # 不好的做法 def complex_decorator(func): def wrapper(*args, **kwargs): # 过多的逻辑处理 result = complex_operation_1() if result: value = complex_operation_2() if value: return func(*args, **kwargs) return None return wrapper # 好的做法 def simple_decorator(func): @wraps(func) def wrapper(*args, **kwargs): # 简单明确的逻辑 if not check_condition(): return None return func(*args, **kwargs) return wrapper ``` 3. **正确处理参数** ```python # 不好的做法 def bad_decorator(func): def wrapper(x, y): return func(x, y) return wrapper # 好的做法 def good_decorator(func): @wraps(func) def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper ``` 4. **合理使用类装饰器** ```python # 不好的做法 def stateful_decorator(func): count = 0 # 状态在模块级别 def wrapper(*args, **kwargs): nonlocal count count += 1 return func(*args, **kwargs) return wrapper # 好的做法 class StatefulDecorator: def __init__(self, func): self.func = func self.count = 0 def __call__(self, *args, **kwargs): self.count += 1 return self.func(*args, **kwargs) ``` 通过本文的学习,你应该已经掌握了Python装饰器的基本概念、工作原理以及实际应用方法。装饰器是Python中非常强大的特性,合理使用它可以让代码更加简洁、可维护。继续练习和探索,你会发现更多装饰器的应用场景!