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

PyTest中@singledispatch与@typechecked未触发预期NotImplementedError问题

解决 test_score_not_implemented_error() 测试用例通过问题

问题根源分析

  1. @typechecked 装饰器冲突:该装饰器会在函数执行前强制校验参数类型,不符合要求的参数会直接抛出 TypeCheckError,根本无法触发我们自定义的 NotImplementedError 逻辑,导致测试失败。
  2. 移除 @typechecked 后的 TypeError:说明多态分支的匹配逻辑存在漏洞,非目标类型参数错误进入了某个分支,触发了不兼容的运算(比如对字符串做加减/求和操作)。

解决方案:分层实现多态与异常转换

通过拆分函数为内层多态实现和外层异常转换层,既保留类型校验的安全性,又能正确触发自定义异常。

代码示例

from functools import singledispatch
from typeguard import typechecked, TypeCheckError
from typing import List, Any

# 内层:负责多态分支的类型校验与业务逻辑
@singledispatch
def _score(count_neg, count_pos):
    raise NotImplementedError("Unsupported parameter types")

# 注册 Tuple[int, int] 类型分支
@_score.register
@typechecked
def _(count_neg: int, count_pos: int):
    total = count_pos + count_neg
    return (count_pos - count_neg) / total if total != 0 else 0

# 注册 Tuple[List[int], List[int]] 类型分支
@_score.register
@typechecked
def _(count_neg: List[int], count_pos: List[int]):
    total_neg = sum(count_neg)
    total_pos = sum(count_pos)
    total = total_pos + total_neg
    return (total_pos - total_neg) / total if total != 0 else 0

# 外层:捕获类型校验异常,转换为要求的 NotImplementedError
def score(count_neg: Any, count_pos: Any):
    try:
        return _score(count_neg, count_pos)
    except TypeCheckError:
        raise NotImplementedError("Unsupported parameter types") from None

逻辑说明

  1. 内层 _score:通过 @singledispatch 实现多态,每个分支用 @typechecked 确保参数类型合法,避免运算时出现 TypeError。
  2. 外层 score:作为对外接口,捕获内层抛出的 TypeCheckError(即参数不符合任何注册分支的类型要求),转换为测试用例要求的 NotImplementedError。

测试用例验证

def test_score_not_implemented_error():
    # 测试字符串类型参数
    try:
        score("invalid", "invalid")
        assert False, "Expected NotImplementedError"
    except NotImplementedError:
        pass

    # 测试混合类型参数
    try:
        score(1, [2])
        assert False, "Expected NotImplementedError"
    except NotImplementedError:
        pass

    # 测试合法类型(验证正常逻辑不被影响)
    assert score(3, 7) == 0.4
    assert score([1,2], [3,4]) == (7-3)/(7+3) == 0.4

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 20:15:16