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

如何让装饰器不覆盖原函数的类型提示?

解决装饰器覆盖原函数类型提示的问题

你的问题出在装饰器的类型注解太泛化——当前装饰器返回的是通用的Callable,导致原函数的参数名称、类型和返回类型信息都被覆盖了,调用时只能看到(...) -> Any的模糊提示。要让被装饰后的函数保留原函数的完整类型提示,可以用泛型类型注解来定义装饰器,具体实现如下:

修改后的代码

from typing import Callable, ParamSpec, TypeVar
import functools

# 定义泛型参数,捕获原函数的参数规格和返回类型
P = ParamSpec("P")
R = TypeVar("R")

def decorator(fn: Callable[P, R]) -> Callable[P, R]:
    # 使用functools.wraps继承原函数的元数据(非类型提示必需,但能提升使用体验)
    @functools.wraps(fn)
    def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
        return fn(*args, **kwargs)
    
    return wrapper


@decorator
def foo_with_decorator(x: int, y: int) -> float:
    return x + y / 2

def foo(x: int, y: int) -> float:
    return x + y / 2

foo_with_decorator(10, 5)  # 现在会显示完整类型提示:(x: int, y: int) -> float
foo(10, 5)  # (x: int, y: int) -> float

关键说明

  • ParamSpec("P"):专门用来捕获函数的参数规格(包含位置参数、关键字参数的类型和名称信息)
  • TypeVar("R"):用来捕获原函数的返回类型
  • 装饰器的类型注解Callable[P, R]明确了:输入一个参数规格为P、返回类型为R的函数,输出一个完全相同参数和返回类型的函数,这样类型检查工具就能保留原函数的所有类型提示
  • functools.wraps(fn):虽然不直接影响类型提示,但它会让装饰后的函数继承原函数的函数名、文档字符串等元数据,让调试和调用更贴近原函数的体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 07:30:49