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

如何用Python typing.TypeVar指定继承多个基类的类型约束?

问题

我们知道Python的TypeVar可以通过bound参数设置类型约束,示例如下:

from typing import TypeVar

class A:
    pass

T = TypeVar("T", bound=A)

def foo(_: T) -> None:
    pass

class B(A):
    pass

class C:
    pass

foo(B())  # OK
foo(C())  # error: Value of type variable "T" of "foo" cannot be "C"

现在需要实现的是:如何表示任意同时继承自X和Y的类型T?

初步尝试通过创建一个同时继承X和Y的中间类XY,再将TypeVar的bound设为XY,但这种方案无效:

from typing import TypeVar

class X:
    pass

class Y:
    pass

class XY(X, Y):
    pass

T = TypeVar("T", bound=XY)

def foo(_: T) -> None:
    pass

class MyClass(X, Y):
    pass

foo(MyClass())  # error: Value of type variable "T" of "foo" cannot be "MyClass"

因为MyClass并非XY的子类,mypy会正确报错。实际场景中,若存在多个基类(X1、X2……Xn),为每个组合创建中间类完全不现实。本质上想要实现类似如下虚构代码的效果:

T = TypeVar("T", bound=(X, Y))  # Not allowed

def foo(x: T):
    assert isinstance(x, X)
    assert isinstance(x, Y)

解决方案

方法1:使用Protocol(推荐)

利用typing.Protocol定义一个同时兼容X和Y的协议,让TypeVar绑定这个协议。协议会自动检查类型是否实现了X和Y的所有成员,自然覆盖同时继承X和Y的情况:

from typing import TypeVar, Protocol

class X:
    pass

class Y:
    pass

class XYProtocol(Protocol):
    __class__: type[X] & type[Y]  # 若X/Y有特定方法/属性,可在此显式声明以增强检查

T = TypeVar("T", bound=XYProtocol)

def foo(_: T) -> None:
    pass

class MyClass(X, Y):
    pass

foo(MyClass())  # OK

方法2:直接使用交集类型(Python 3.10+)

Python 3.10及以上版本支持用X & Y表示同时属于X和Y的类型,无需TypeVar就能实现约束,是最简单直接的方式:

class X:
    pass

class Y:
    pass

def foo(_: X & Y) -> None:
    pass

class MyClass(X, Y):
    pass

foo(MyClass())  # OK

方法3:结合TypeVar和交集类型

如果需要复用这个复合类型约束,可以将TypeVar的bound设为X & Y:

from typing import TypeVar

class X:
    pass

class Y:
    pass

T = TypeVar("T", bound=X & Y)

def foo(_: T) -> None:
    pass

class MyClass(X, Y):
    pass

foo(MyClass())  # OK

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 09:32:52