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

Python装饰器触发Mypy 'Untyped'类型检查错误的解决方法

解决Mypy报"Untyped decorator makes function 'score' untyped"的问题

核心原因

Mypy无法识别装饰器的类型签名,尤其是装饰类方法时,若未正确标注装饰器的泛型类型以匹配原函数的参数(包括类实例self)和返回值,就会触发该错误。

修复方案

使用typing模块的ParamSpec和TypeVar来保留被装饰函数的完整类型信息,让Mypy能正确推断装饰后函数的类型。

1. 基础无参数装饰器示例

from typing import Callable, TypeVar, ParamSpec

# 定义参数规范和返回值类型变量
P = ParamSpec("P")
R = TypeVar("R")

def process_without_columns(func: Callable[P, R]) -> Callable[P, R]:
    def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
        # 这里写你的装饰器逻辑,比如移除columns参数
        kwargs.pop("columns", None)
        return func(*args, **kwargs)
    return wrapper

2. 类方法中使用装饰器

class Scorer:
    @process_without_columns
    def score(self, data: dict, columns: list[str] | None = None) -> float:
        # 你的业务逻辑
        return 0.5

3. 带参数的装饰器(如果需要)

如果你的装饰器需要接收额外参数,需嵌套一层并保持类型注解的一致性:

from typing import Callable, TypeVar, ParamSpec

P = ParamSpec("P")
R = TypeVar("R")

def process_without_columns(exclude_cols: list[str]):
    def decorator(func: Callable[P, R]) -> Callable[P, R]:
        def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
            # 根据传入的参数处理kwargs
            for col in exclude_cols:
                kwargs.pop(col, None)
            return func(*args, **kwargs)
        return wrapper
    return decorator

# 使用示例
class Scorer:
    @process_without_columns(exclude_cols=["columns", "extra"])
    def score(self, data: dict, columns: list[str] | None = None) -> float:
        return 0.5

关键注意事项

  • 确保使用Python 3.10+或Mypy 0.910+,旧版本对ParamSpec的支持不完善
  • 装饰器的输入和输出必须严格匹配Callable[P, R],保证类型信息不丢失
  • 若装饰器修改了原函数的参数或返回值,需调整类型注解以匹配实际行为

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 09:27:25