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

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

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


🎯 练习目标

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

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

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

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

举个例子:

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()

输出:

r 复制代码
Before call!
Hello!
After call!

换成语法糖的写法就是:

python 复制代码
@shout_decorator
def greet():
    print("Hello!")

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

目标功能:

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

🔧 步骤 1:基础版装饰器

python 复制代码
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

用法示例:

python 复制代码
@timeit
def add(a, b):
    time.sleep(0.5)
    return a + b

print(add(10, 20))

输出:

csharp 复制代码
⏱ 正在执行函数: add
✅ 函数 add 执行完成,用时 0.5003 秒
30

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

python 复制代码
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:再测几个函数

python 复制代码
@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. 参数化装饰器(带参数的装饰器)

python 复制代码
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

python 复制代码
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 次);
  • 把多个装饰器组合使用,看函数执行顺序。

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

相关推荐
笨鸟先飞,勤能补拙4 小时前
AI 赋能网络安全:技术全景、成熟度评估与实战案例
人工智能·python·安全·web安全·网络安全·sqlite·github
长和信泰光伏储能4 小时前
京津冀光伏发电:绿色能源的未来之路
python·能源
浦信仿真大讲堂5 小时前
从重复操作到自动化闭环:如何让 CST 与 Python 真正协同起来
python·自动化·cst·仿真软件·达索软件
Gu Gu Study5 小时前
ScoutLoop开放域深度研究引擎(agent的初步设计想法)
人工智能·python
卷无止境6 小时前
写代码这件事,到底该讲究点什么?
后端·python
卷无止境6 小时前
循环复杂度到底在算什么,Python 代码怎么才能写得让人一看就懂
后端·python
lpfasd1236 小时前
MediaCrawler 项目深度分析
chrome·python·chrome devtools
Dxy12393102167 小时前
Python项目打包成EXE完整教程(PyInstaller实战避坑)
开发语言·python
bamb007 小时前
一个项目带你入门AI应用开发01
python
0566467 小时前
Python康复训练——常用标准库
开发语言·python·学习