为返回DataFrame的函数添加计时装饰器时出现'DataFrame' object is not callable报错
报错根因
错误完全来自装饰器的返回逻辑写错了调用时机:
- 按照Python装饰器的执行流程,
@timer作用在generate_df上时,等价于执行generate_df = timer(generate_df)。 - 你写的
timer函数内部定义完包装函数wrapper_timer后,直接写了return wrapper_timer()——带括号的写法会立刻执行一次wrapper_timer:这一步里会直接运行原generate_df读CSV的逻辑,把得到的DataFrame对象作为timer的最终返回值。 - 这时候原本的函数名
generate_df已经被替换成了上面说的DataFrame对象,后续代码再写df = generate_df()时,本质是给DataFrame对象加括号做调用操作,自然触发'DataFrame' object is not callable报错。
修正要点
- 去掉
timer函数最后一行wrapper_timer后面的括号,也就是把return wrapper_timer()改成return wrapper_timer,让装饰器返回可调用的包装函数本身,而不是提前执行得到的结果。 - 给内部的
wrapper_timer补充可变参数适配(增加*args, **kwargs入参,调用原函数时透传参数),避免后续被装饰函数需要传参时出现参数不匹配的问题。
修正后可运行的完整代码
import pandas as pd import time import functools def timer(func): @functools.wraps(func) def wrapper_timer(*args, **kwargs): start_time = time.perf_counter() value = func(*args, **kwargs) end_time = time.perf_counter() run_time = end_time - start_time print(f"Finished {func.__name__!r} in {run_time:.4f} secs") return value return wrapper_timer @timer def generate_df(): file="file.csv" df = pd.read_csv(file) return df if __name__ == '__main__': df = generate_df() print(df.head())
内容的提问来源于stack exchange,提问作者Fahad Vadakkumpadatah
相关产品推荐
相关产品推荐

