You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python通用操作计时函数的文档编写、类型提示及最佳实践问询

Python 计时函数的实现与优化

先解决你遇到的计时结果为0的核心问题:你直接传入了函数调用(比如timer(crawl_data())),这会先执行crawl_data(),把执行结果传给计时函数,而不是让计时函数触发执行。正确做法是让计时函数接收可调用对象(函数本身)和它的参数,在函数内部延迟执行。


1. 任意类型参数/返回值的函数文档编写

用标准docstring(以Google风格为例),明确说明参数、返回值含义,搭配示例:

import time
from typing import Callable, TypeVar, Any

T = TypeVar('T')

def timer(func: Callable[..., T], *args: Any, **kwargs: Any) -> tuple[float, T]:
    """计算指定函数的执行耗时,返回耗时与原函数返回值。

    Args:
        func: 要计时的可调用对象(函数、方法等)
        *args: 传递给func的位置参数
        **kwargs: 传递给func的关键字参数

    Returns:
        元组,第一个元素为执行耗时(单位:秒),第二个元素为func的返回值

    Examples:
        >>> def add(a, b):
        ...     time.sleep(0.1)
        ...     return a + b
        >>> cost, result = timer(add, 1, 2)
        >>> print(f"耗时: {cost:.2f}s, 结果: {result}")
        耗时: 0.10s, 结果: 3
    """
    start = time.perf_counter()
    result = func(*args, **kwargs)
    end = time.perf_counter()
    return (end - start, result)

2. 类型提示的添加

通过typing模块的泛型和可调用类型标注,实现任意参数/返回值的类型提示:

  • 用TypeVar('T')定义泛型类型,指代原函数的返回值类型
  • Callable[..., T]表示接收任意参数、返回T类型的可调用对象
  • *args: Any和**kwargs: Any表示接收任意类型的位置/关键字参数
  • 返回值标注为tuple[float, T],即(耗时,原函数返回值)的元组

完整类型提示代码如上一节所示。

3. 最佳实践:无需回到重复代码

绝对不要回到重复代码,DRY原则的应用是正确方向。你当前的实现可以优化为更Pythonic的方案:

方案1:装饰器(适合给单个函数添加计时)

import time
from typing import Callable, TypeVar

T = TypeVar('T')

def timer_decorator(func: Callable[..., T]) -> Callable[..., tuple[float, T]]:
    def wrapper(*args, **kwargs) -> tuple[float, T]:
        start = time.perf_counter()
        result = func(*args, **kwargs)
        end = time.perf_counter()
        return (end - start, result)
    return wrapper

# 使用方式
@timer_decorator
def crawl_data():
    # 爬取逻辑示例
    time.sleep(0.2)
    return {"data": "sample"}

cost, data = crawl_data()
print(f"爬取耗时: {cost:.2f}s")

方案2:上下文管理器(适合给任意代码块计时)

import time
from contextlib import contextmanager
from typing import Generator

@contextmanager
def timer_context() -> Generator[None, None, float]:
    start = time.perf_counter()
    try:
        yield
    finally:
        end = time.perf_counter()
        yield end - start

# 使用方式
with timer_context() as cost:
    # CSV读取逻辑示例
    time.sleep(0.15)
print(f"CSV读取耗时: {cost:.2f}s")

这两种方式比函数调用式更简洁,也符合Python惯用写法。如果只是简单计时需求,也可以用标准库timeit模块,但自定义装饰器/上下文管理器更灵活,能适配你流程中的各类步骤。


内容的提问来源于stack exchange,提问作者bismo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 17:35:25