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

如何在mypy中指定函数一个参数为另一参数类型的子类

实现参数类型约束的解决方案

首先说明两个核心问题的背景:

  1. 你尝试将T2的bound绑定到另一个TypeVar T的写法报错,是因为Python的类型系统(遵循PEP 484规范)不允许TypeVar的约束条件使用其他TypeVar做参数,所以会抛出Constraints cannot be parametrized by type variables错误。
  2. 单个TypeVar的写法无法达到预期,是因为类型检查器做类型推导时,会自动取两个参数的最小公共父类作为TypeVar的实际类型,比如调用f(B(), A())时,TypeVar会被推导为A,自然就通过了检查,没法约束第二个参数必须是第一个参数类型的子类。

可落地的实现方案

方案1:通用兼容方案(支持所有Python 3.6+版本)

利用不变泛型的特性强制类型推导优先取第一个参数的精确类型,禁止自动向上转型,实现成本很低:

from typing import TypeVar, Generic

T = TypeVar('T')
# 不变泛型包装类,不声明协变/逆变即为默认不变,禁止参数类型向上/向下转型推导
class InvariantWrap(Generic[T]):
    __slots__ = ('val',)
    def __init__(self, val: T):
        self.val = val

def f(a: InvariantWrap[T], b: T) -> None:
    # 业务逻辑中通过a.val取用第一个参数的原始值
    ...

# 调用测试
f(InvariantWrap(A()), B()) # 类型检查通过
f(InvariantWrap(B()), A()) # 类型检查报错
f(InvariantWrap(A()), C()) # 类型检查报错

方案2:精简方案(仅适用于入参为类对象的场景)

如果你可以调整函数逻辑,直接接收类对象而非实例,写法可以更简单:

from typing import TypeVar

T = TypeVar('T')

def f(a: type[T], b: type[T]) -> None:
    ...

# 调用测试
f(A, B) # 类型检查通过
f(B, A) # 类型检查报错
f(A, C) # 类型检查报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 06:57:03