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

Python小练习系列 Vol.13:用装饰器记录函数执行时间

🧩 Python小练习系列 Vol.13:用装饰器记录函数执行时间

本节是 Python 小练习系列的一个子题,带你理解并动手写出一个能实用、可拓展的装饰器。


🎯 练习目标

  • 理解 Python 装饰器(Decorator)的工作原理;
  • 学会使用 @ 装饰器语法糖;
  • 编写一个记录函数运行时间的装饰器;
  • 掌握 functools.wraps 的正确使用方式;
  • 探索装饰器进阶应用场景。

🧠 一分钟理解什么是装饰器

“不改原函数的代码,就能给它增加功能?”

是的!装饰器是 Python 中的一种语法糖,它其实是一个返回函数的函数。装饰器常用于日志记录、权限验证、性能统计、缓存等场景。

举个例子:

def greet():
    print("Hello!")

# 给 greet 函数加个装饰器:
def shout_decorator(func):
    def wrapper():
        print("Before call!")
        func()
        print("After call!")
    return wrapper

greet = shout_decorator(greet)
greet()

输出:

Before call!
Hello!
After call!

换成语法糖的写法就是:

@shout_decorator
def greet():
    print("Hello!")

💡 我们的练习:计时装饰器 @timeit

目标功能:

  • @timeit 装饰任意函数;
  • 执行前记录函数名;
  • 执行后打印运行时间(精确到毫秒);
  • 返回原函数的执行结果。

🔧 步骤 1:基础版装饰器

import time

def timeit(func):
    def wrapper(*args, **kwargs):
        print(f"⏱ 正在执行函数: {func.__name__}")
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"✅ 函数 {func.__name__} 执行完成,用时 {end - start:.4f} 秒")
        return result
    return wrapper

用法示例:

@timeit
def add(a, b):
    time.sleep(0.5)
    return a + b

print(add(10, 20))

输出:

⏱ 正在执行函数: add
✅ 函数 add 执行完成,用时 0.5003 秒
30

⚠️ 步骤 2:加入 functools.wraps 避免元信息丢失

import functools

def timeit(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print(f"⏱ 正在执行函数: {func.__name__}")
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"✅ 函数 {func.__name__} 执行完成,用时 {end - start:.4f} 秒")
        return result
    return wrapper

🧪 步骤 3:再测几个函数

@timeit
def multiply(a, b):
    time.sleep(0.8)
    return a * b

@timeit
def say_hello(name):
    print(f"Hello, {name}!")

multiply(3, 4)
say_hello("Python")

🚀 进阶挑战(可选)

1. 参数化装饰器(带参数的装饰器)

def timeit(verbose=True):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            if verbose:
                print(f"⏱ 正在执行函数: {func.__name__}")
            start = time.time()
            result = func(*args, **kwargs)
            end = time.time()
            if verbose:
                print(f"✅ 函数 {func.__name__} 执行完成,用时 {end - start:.4f} 秒")
            return result
        return wrapper
    return decorator

@timeit(verbose=False)
def fast_add(a, b):
    return a + b

2. 装饰异步函数(使用 asyncio

import asyncio

def async_timeit(func):
    @functools.wraps(func)
    async def wrapper(*args, **kwargs):
        start = time.time()
        result = await func(*args, **kwargs)
        end = time.time()
        print(f"✅ 异步函数 {func.__name__} 执行完成,用时 {end - start:.4f} 秒")
        return result
    return wrapper

@async_timeit
async def async_task():
    await asyncio.sleep(1)

asyncio.run(async_task())

📌 总结

技能点说明
@装饰器增强函数功能的利器
*args, **kwargs保证适配各种函数参数
functools.wraps保持原函数元信息
参数化装饰器更加灵活的扩展方式
异步函数装饰器用于 async def 函数的异步装饰器

📚 推荐练习拓展

  • 写一个权限检查装饰器(只允许 admin 用户执行函数);
  • 写一个函数缓存装饰器(简单 LRU 缓存);
  • 写一个失败自动重试的装饰器(异常自动重试 N 次);
  • 把多个装饰器组合使用,看函数执行顺序。

如果这篇内容对你有帮助,
欢迎 点赞 👍 | 收藏 ⭐ | 关注 ❤️
如果你有更好的想法,欢迎评论区留言分享~

http://www.dtcms.com/a/117764.html

相关文章:

  • 蓝桥杯2024年第十五届省赛真题-爬山
  • 刺杀大使--bfs还是比dfs快+二分
  • 专题|MATLAB-R语言Logistic逻辑回归增长模型在互联网金融共生及移动通信客户流失分析实例合集
  • 基于Python Flask快速构建网络安全工具资源库的Web应用实践
  • 【简历全景认知2】电子化时代对简历形式的降维打击:从A4纸到ATS的生存游戏
  • Python高阶函数-filter
  • es 原生linux部署集群
  • JS 中html的document
  • MySQL学习笔记六
  • Python爬虫生成CSV文件的完整流程
  • 谷歌洽谈租赁英伟达AI服务器:算力争夺战再升级
  • 过剩与稀缺:现代社会的思考与启示
  • 信息系统项目管理师-第十一章-项目成本管理
  • R语言:气象水文领域的数据分析与绘图利器
  • 属性修改器 (AttributeModifier)
  • 2024年已备案大模型发展趋势分析
  • spring boot + Prometheus + Grafana 实现项目监控
  • 2️⃣ Coze创建智能体教学(2025年全新版本)
  • 探索轻量高性能的 Rust HTTP 服务器框架 —— Hyperlane
  • 内存管理及内建函数
  • AI芯片混战:GPU vs TPU vs NPU的算力与能效博弈
  • 嵌入式软硬件开发,常见通信总线
  • Spring启示录、概述、入门程序以及Spring对IoC的实现
  • Spring Boot 框架注解:@ConfigurationProperties
  • Java文件流操作 - 【Guava】IO工具
  • React 列表与 Keys 的深入探讨
  • 聊聊Spring AI的PgVectorStore
  • OpenCV 图形API(17)计算输入矩阵 src 中每个元素的平方根函数sqrt()
  • oklink js逆向(入口定位)
  • 1.2 测试设计阶段:打造高质量的测试用例