当前位置: 首页 > news >正文

Day 27 训练

Day 27 训练

  • Python装饰器详解:从原理到实践,深入理解语法糖
    • 一、装饰器原理揭秘:优雅的语法糖背后
      • 1.1 装饰器的核心执行流程
      • 1.2 装饰器结构剖析
    • 二、进阶实战:处理带参数的函数
      • 2.1 可变参数解决方案
      • 2.2 参数处理要点
    • 三、实战案例:日志记录装饰器
      • 3.1 完整实现代码
      • 3.2 执行结果演示
      • 3.3 常见错误示例
    • 四、装饰器开发最佳实践
      • 4.1 关键注意事项
      • 4.2 调试技巧
    • 五、扩展应用场景


Python装饰器详解:从原理到实践,深入理解语法糖

一、装饰器原理揭秘:优雅的语法糖背后

1.1 装饰器的核心执行流程

装饰器的本质是一个高阶函数,其执行流程可以分解为以下步骤:

def display_time(func):  # 装饰器函数def wrapper():t1 = time.time()func()          # 调用原函数t2 = time.time()print(f"耗时: {t2-t1}秒")return wrapper@display_time           # 等价于 prime_nums = display_time(prime_nums)
def prime_nums():       # 被装饰函数# 计算素数代码...prime_nums()            # 实际调用的是wrapper()

关键点解析:

  • 函数替换:装饰后原函数名指向wrapper函数
  • 执行时机:@语法在模块加载时立即执行
  • 隐式传递:Python自动传递被装饰函数给装饰器

1.2 装饰器结构剖析

组成部分作用说明
外层装饰器函数接收被装饰函数,返回包装函数
内层包装函数实现功能扩展,最终调用原函数
@语法糖简化装饰器应用语法

二、进阶实战:处理带参数的函数

2.1 可变参数解决方案

当被装饰函数需要接收参数时,需要使用*args和**kwargs:

def display_time(func):def wrapper(*args, **kwargs):  # 接收任意参数t1 = time.time()result = func(*args, **kwargs)  # 解包参数print(f"耗时: {time.time()-t1}秒")return result  # 返回原函数结果return wrapper@display_time
def add(a, b):return a + bprint(add(3, 5))  # 输出:8 和耗时信息

2.2 参数处理要点

  1. 参数透传:wrapper必须与被装饰函数参数兼容
  2. 返回值处理:必须显式返回原函数结果
  3. 参数类型
    • *args:接收位置参数元组
    • **kwargs:接收关键字参数字典

三、实战案例:日志记录装饰器

3.1 完整实现代码

def logger(func):"""记录函数执行日志的装饰器"""def wrapper(*args, **kwargs):print(f"[开始] {func.__name__},参数: {args}, {kwargs}")result = func(*args, **kwargs)print(f"[结束] {func.__name__},返回值: {result}")return resultreturn wrapper@logger
def multiply(a, b):return a * b# 测试不同调用方式
multiply(2, 3)          # 位置参数
multiply(a=2, b=3)      # 关键字参数
multiply(2, b=3)        # 混合参数

3.2 执行结果演示

[开始] multiply,参数: (2, 3), {}
[结束] multiply,返回值: 6
[开始] multiply,参数: (), {'a': 2, 'b': 3}
[结束] multiply,返回值: 6
[开始] multiply,参数: (2,), {'b': 3}
[结束] multiply,返回值: 6

3.3 常见错误示例

multiply(a=2, 3)  # 错误!关键字参数必须在位置参数之后

报错分析:

SyntaxError: positional argument follows keyword argument

原因:Python语法规定所有位置参数必须出现在关键字参数之前

四、装饰器开发最佳实践

4.1 关键注意事项

  1. 保留元信息:使用@functools.wraps(func)装饰wrapper
  2. 多层装饰器:装饰顺序影响执行顺序(从下往上)
  3. 带参装饰器:需要三层嵌套函数结构
  4. 性能影响:每次调用都会执行装饰器逻辑

4.2 调试技巧

  • 使用__name__属性检查函数身份
print(multiply.__name__)  # 输出:wrapper(未使用functools时)

五、扩展应用场景

场景类型实现功能示例应用
性能监控统计函数执行时间接口响应时间统计
权限校验验证用户访问权限登录状态检查
缓存机制缓存函数计算结果斐波那契数列计算
异常处理统一异常捕获和日志记录数据库操作重试机制
输入验证验证函数参数合法性API参数校验
# 带缓存功能的装饰器示例
from functools import lru_cache@lru_cache(maxsize=128)
@logger
def factorial(n):return n * factorial(n-1) if n else 1

掌握装饰器技巧,可以显著提升代码的复用性和可维护性。建议读者尝试实现一个支持超时中断的装饰器,这将涉及信号处理和多线程技术,是很好的进阶练习。
@浙大疏锦行

http://www.xdnf.cn/news/577549.html

相关文章:

  • Linux中的文件介绍
  • 通过美图秀秀将多张图片合并
  • 【UEFI实战】BIOS编译过程中报错“无法解析的外部符号memcpy”
  • 七: NumPy的使用
  • vue+srpingboot实现多文件导出
  • Unity中GPU Instancing使用整理
  • Python训练Day30
  • 第3周作业-1层隐藏层的神经网络分类二维数据
  • MQTT报文介绍
  • Linux内存分页管理详解
  • Jsoup解析商品信息具体怎么写?
  • 阿里发布扩散模型Wan VACE,全面支持生图、生视频、图像编辑,适配低显存~
  • FreeCAD傻瓜教程-外螺纹的绘制,利用两个实体进行布尔运算来实现
  • 《P1433 吃奶酪》
  • MCU开发学习记录19* - CAN学习与实践(HAL库) - 定时传输、触发传输和请求传输(轮询与中断实现) -STM32CubeMX
  • Python 代码缩进与结构化编程:从基础到风格规范
  • Robotaxi新消息密集释放,量产元年来临谁在领跑?
  • [Java恶补day2] 49. 字母异位词分组
  • 【SW】从3D模型导出dxf图纸
  • 【算法专题十五】BFS解决最短路问题
  • 04_Prometheus监控docker容器(4)
  • 智慧社区新防线:华奥系AI技术如何让夏季安防“零隐患”
  • 如何在JavaScript中将数值转换为字符串并赋值给数组——以RuoYi-Vue项目为例
  • Redis Cluster动态扩容:架构原理与核心机制解析
  • 航电系统之航点跟踪系统篇
  • C++(27): 标准库 <iterator>
  • 逆向音乐APP:Python爬虫获取音乐榜单 (1)
  • Podman(Pod Manager)简介
  • 嵌入式STM32学习——串口USART 2.1(串口发送字符串和字符)
  • 应用分享 | 软件定义架构如何满足GNSS模拟测试的开放性需求?