Python装饰器详解

Python装饰器详解

装饰器(Decorator)是 Python 中一种强大的语法特性,允许在不修改原始代码的情况下动态扩展函数或类的功能。以下是其语法、用法、优缺点及常见使用场景的详细说明:

一、装饰器语法

1. 基本结构

装饰器本质上是一个可调用对象(函数或类),接受一个函数作为输入,返回一个新的函数(或类)。

def decorator(func):def wrapper(*args, **kwargs):# 前置操作(如日志、权限校验)result = func(*args, **kwargs)  # 调用原函数# 后置操作(如数据处理、清理)return resultreturn wrapper@decorator  # 等价于 func = decorator(func)
def func():pass

2. 带参数的装饰器

通过嵌套函数实现装饰器参数传递:

def decorator_with_args(param):def actual_decorator(func):def wrapper(*args, **kwargs):print(f"Decorator param: {param}")return func(*args, **kwargs)return wrapperreturn actual_decorator@decorator_with_args("config")
def func():pass

3. 类装饰器

通过实现 __call__ 方法让类的实例成为装饰器:

class ClassDecorator:def __init__(self, func):self.func = funcdef __call__(self, *args, **kwargs):print("Class decorator")return self.func(*args, **kwargs)@ClassDecorator
def func():pass

4. 多个装饰器叠加

执行顺序:从下往上(靠近函数的装饰器先执行):

@decorator1
@decorator2
def func():pass
# 等价于 func = decorator1(decorator2(func))

二、优点

  • 代码复用性:将通用功能(如日志、权限校验)抽离成装饰器,避免重复代码。
  • 非侵入式扩展:遵循开放-封闭原则(对扩展开放,对修改封闭),无需修改原函数代码。
  • 简洁性:通过 @ 语法让代码更清晰,逻辑分离更明确。
  • 灵活组合:多个装饰器可叠加使用,灵活组合不同功能。

三、缺点

  • 调试困难:装饰器可能隐藏原函数的元信息(如 __name__、文档字符串),需用 functools.wraps 修复:

    from functools import wraps
    def decorator(func):@wraps(func)  # 保留原函数元信息def wrapper(*args, **kwargs):return func(*args, **kwargs)return wrapper
    
  • 过度嵌套:多层装饰器可能导致代码可读性下降。

  • 隐式行为:装饰器的副作用可能导致代码行为难以预测(尤其是第三方装饰器)。

四、常见使用场景

1. 日志记录

import time
from functools import wrapsdef log_time(func):@wraps(func)def wrapper(*args, **kwargs):start = time.time()result = func(*args, **kwargs)end = time.time()print(f"Function {func.__name__} took {end - start:.2f} seconds to run.")return resultreturn wrapper@log_time
def example_function(n):sum = 0for i in range(n):sum += ireturn sumresult = example_function(1000000)
print(f"Result: {result}")

运行结果:

Function example_function took 0.07 seconds to run.
Result: 499999500000

2. 权限校验

from functools import wrapsclass User:def __init__(self, authenticated):self.is_authenticated = authenticateddef login_required(func):@wraps(func)def wrapper(user, *args, **kwargs):if not user.is_authenticated:raise PermissionError("User not logged in")return func(user, *args, **kwargs)return wrapper@login_required
def admin_dashboard(user):return "Welcome to the admin dashboard!"user = User(authenticated=True)
print(admin_dashboard(user))user = User(authenticated=False)
try:print(admin_dashboard(user))
except PermissionError as e:print(e)

运行结果:

Welcome to the admin dashboard!
User not logged in

3. 缓存(Memoization)

from functools import lru_cache@lru_cache(maxsize=128)
def fibonacci(n):if n < 2:return nreturn fibonacci(n-1) + fibonacci(n-2)print(fibonacci(10))

运行结果:

55

4. 路由注册

from flask import Flaskapp = Flask(__name__)@app.route("/")
def home():return "Hello World"@app.route("/about")
def about():return "About Page"if __name__ == "__main__":app.run(debug=True)

运行结果:

* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 123-456-789

访问 http://127.0.0.1:5000/ 将显示 “Hello World”,访问 http://127.0.0.1:5000/about 将显示 “About Page”。

5. 性能监控

from functools import wraps
import time
import tracemallocdef performance_monitor(func):@wraps(func)def wrapper(*args, **kwargs):tracemalloc.start()start_time = time.time()result = func(*args, **kwargs)end_time = time.time()current, peak = tracemalloc.get_traced_memory()tracemalloc.stop()print(f"Function {func.__name__} executed in {end_time - start_time:.2f}s")print(f"Memory usage: Current = {current / 10**6:.2f}MB, Peak = {peak / 10**6:.2f}MB")return resultreturn wrapper@performance_monitor
def memory_intensive_function():data = [i for i in range(1000000)]return len(data)memory_intensive_function()

运行结果:

Function memory_intensive_function executed in 0.07s
Memory usage: Current = 7.63MB, Peak = 7.63MB

五、总结

  • 适用场景:需要为多个函数统一添加公共功能的场景(如日志、缓存、校验)。
  • 慎用场景:过度使用会导致代码复杂化,尤其是多层装饰器嵌套时。
  • 最佳实践:保持装饰器功能单一,使用 functools.wraps 保留元信息,避免深层嵌套。

装饰器是 Python 高阶编程的核心工具之一,合理使用可以显著提升代码质量和可维护性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/34471.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

matlab 控制系统GUI设计-PID控制超前滞后控制

1、内容简介 matlab164-控制系统GUI设计-PID控制超前滞后控制 可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略

【大模型基础_毛玉仁】2.4 基于 Encoder-Decoder 架构的大语言模型

更多内容&#xff1a;XiaoJ的知识星球 目录 2.4 基于 Encoder-Decoder 架构的大语言模型2.4.1 Encoder-Decoder 架构2.4.2 T5 语言模型1&#xff09;T5 模型结构2&#xff09;T5 预训练方式3&#xff09;T5 下游任务 2.4.3 BART 语言模型1&#xff09;BART 模型结构2&#xff0…

AI智能代码疫苗技术,赋能数字化应用内生安全自免疫

“DevSecOps市占率持续领先&#xff0c;IAST探针覆盖率十倍增长&#xff0c;代码疫苗技术已成功帮助上千家行业用户成功抵御‘Log4j2.x’等重大未知漏洞的利用攻击。”子芽在腾讯专访中透露。 这是2021年悬镜安全交出的一张成绩单。悬镜安全是DevSecOps敏捷安全先行者&#xf…

【初级篇】如何使用DeepSeek和Dify构建高效的企业级智能客服系统

在当今数字化时代,企业面临着日益增长的客户服务需求。使用Dify创建智能客服不仅能够提升客户体验,还能显著提高企业的运营效率。关于DIfy的安装部署,大家可以参考之前的文章: 【入门级篇】Dify安装+DeepSeek模型配置保姆级教程_mindie dify deepseek-CSDN博客 AI智能客服…

【机器学习-基础知识】统计和贝叶斯推断

1. 概率论基本概念回顾 1. 概率分布 定义: 概率分布(Probability Distribution)指的是随机变量所有可能取值及其对应概率的集合。它描述了一个随机变量可能取的所有值以及每个值被取到的概率。 对于离散型随机变量,使用概率质量函数来描述。对于连续型随机变量,使用概率…

正点原子[第三期]Arm(iMX6U)Linux移植学习笔记-4 uboot目录分析

前言&#xff1a; 本文是根据哔哩哔哩网站上“Arm(iMX6U)Linux系统移植和根文件系统构键篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。 引用&#xff1a; …

视频AI方案:数据+算力+算法,人工智能的三大基石

背景分析 随着信息技术的迅猛发展&#xff0c;人工智能&#xff08;AI&#xff09;已经逐渐渗透到我们生活的各个领域&#xff0c;从智能家居到自动驾驶&#xff0c;从医疗诊断到金融风控&#xff0c;AI的应用正在改变着我们的生活方式。而数据、算法和算力&#xff0c;正是构…

MySQL -- 表的约束

概念引入&#xff1a;真正的约束表字段的是数据类型&#xff0c;但是数据类型的约束方式比较单一的&#xff0c;所以需要一些额外的一些约束&#xff0c;用于表示数据的合法性&#xff0c;在只有数据类型一种约束的情况下&#xff0c;我们比较难保证数据是百分百合法。通过添加…

嵌入式Zephyr RTOS面试题及参考答案

目录 Zephyr RTOS 的主要设计目标是什么?适用于哪些领域? Zephyr 支持哪些内核对象类型?举例说明其应用场景。 Zephyr 支持哪些线程同步机制?举例说明其适用场景。 Zephyr 内核支持哪些任务状态?状态转换的条件是什么? Zephyr 如何实现低延迟中断处理?(如直接中断服…

《TCP/IP网络编程》学习笔记 | Chapter 18:多线程服务器端的实现

《TCP/IP网络编程》学习笔记 | Chapter 18&#xff1a;多线程服务器端的实现 《TCP/IP网络编程》学习笔记 | Chapter 18&#xff1a;多线程服务器端的实现线程的概念引入线程的背景线程与进程的区别 线程创建与运行pthread_createpthread_join可在临界区内调用的函数工作&#…

C++相关基础概念之入门讲解(上)

1. 命名空间 C中的命名空间&#xff08;namespace&#xff09;是用来避免命名冲突问题的一种机制。通过将类、函数、变量等封装在命名空间中&#xff0c;可以避免不同部分的代码中出现相同名称的冲突。在C中&#xff0c;可以使用namespace关键字来定义命名空间。 然后我们在调…

创新技术引领软件供应链安全,助力数字中国建设

编者按 随着数字化转型的加速&#xff0c;针对软件供应链的攻击事件呈快速增长态势&#xff0c;目前已成为网络空间安全的焦点。如何将安全嵌入到软件开发到运营的全流程&#xff0c;实现防护技术的自动化、一体化、智能化&#xff0c;成为技术领域追逐的热点。 悬镜安全作为…

PyTorch 系列教程:使用CNN实现图像分类

图像分类是计算机视觉领域的一项基本任务&#xff0c;也是深度学习技术的一个常见应用。近年来&#xff0c;卷积神经网络&#xff08;cnn&#xff09;和PyTorch库的结合由于其易用性和鲁棒性已经成为执行图像分类的流行选择。 理解卷积神经网络&#xff08;cnn&#xff09; 卷…

【2025】基于python+django的驾校招生培训管理系统(源码、万字文档、图文修改、调试答疑)

课题功能结构图如下&#xff1a; 驾校招生培训管理系统设计 一、课题背景 随着机动车保有量的不断增加&#xff0c;人们对驾驶技能的需求也日益增长。驾校作为驾驶培训的主要机构&#xff0c;面临着激烈的市场竞争和学员需求多样化等挑战。传统的驾校管理模式往往依赖于人工操作…

【JavaWeb】快速入门——HTMLCSS

文章目录 一、 HTML简介1、HTML概念2、HTML文件结构3、可视化网页结构 二、 HTML标签语法1、标题标签2、段落标签3、超链接4、换行5、无序列表6、路径7、图片8、块1 盒子模型2 布局标签 三、 使用HTML表格展示数据1、定义表格2、合并单元格横向合并纵向合并 四、 使用HTML表单收…

MySQL 优化方案

一、MySQL 查询过程 MySQL 查询过程是指从客户端发送 SQL 语句到 MySQL 服务器&#xff0c;再到服务器返回结果集的整个过程。这个过程涉及多个组件的协作&#xff0c;包括连接管理、查询解析、优化、执行和结果返回等。 1.1 查询过程的关键组件 连接管理器&#xff1a;管理…

服务性能防腐体系:基于自动化压测的熔断机制

01# 背景 在系统架构的演进过程中&#xff0c;项目初始阶段都会通过压力测试构建安全护城河&#xff0c;此时的服务性能与资源水位保持着黄金比例关系。然而在业务高速发展时期&#xff0c;每个冲刺周期都被切割成以业务需求为单位的开发单元&#xff0c;压力测试逐渐从必选项…

六十天前端强化训练之第二十天React Router 基础详解

欢迎来到编程星辰海的博客讲解 看完可以给一个免费的三连吗&#xff0c;谢谢大佬&#xff01; 目录 一、核心概念 1.1 核心组件 1.2 路由模式对比 二、核心代码示例 2.1 基础路由配置 2.2 动态路由示例 2.3 嵌套路由实现 2.4 完整示例代码 三、关键功能实现效果 四、…

grad_traj_optimization 开源项目

开源项目 grad_traj_optimization 使用教程-CSDN博客 ubuntu如何切换到root用户_ubuntu切换到root用户-CSDN博客 catkin_make: command not found 解决办法_catkin-make not found-CSDN博客 这就说明需要编译的package虽然存在&#xff0c;但不在指定的目录下。catkin_make命…

深圳南柯电子|净水器EMC测试整改:水质安全与电磁兼容性的双赢

在当今注重健康生活的时代&#xff0c;净水器作为家庭用水安全的第一道防线&#xff0c;其性能与安全性备受关注。其中&#xff0c;电磁兼容性&#xff08;EMC&#xff09;测试是净水器产品上市前不可或缺的一环&#xff0c;它直接关系到产品在复杂电磁环境中的稳定运行及不对其…