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

如何编写带类型收窄的自定义isinstance函数签名?

解决方案

要让mypy正确识别支持单个类型和类型元组的constrained_isinstance函数,你需要使用函数重载结合TypeVarTuple和Unpack,明确标注类型元组元素是实例类型的Type包装,而非直接的类型本身。

完整实现代码

from typing import Any, Type, TypeGuard, TypeVar, Union, overload
from typing_extensions import TypeVarTuple, Unpack

# 单个类型场景的类型变量
T = TypeVar("T")
# 多类型场景的类型变量元组
Ts = TypeVarTuple("Ts")

@overload
def constrained_isinstance(obj: Any, cls: Type[T]) -> TypeGuard[T]:
    ...

@overload
def constrained_isinstance(obj: Any, types: tuple[Type[Unpack[Ts]]]) -> TypeGuard[Union[Unpack[Ts]]]:
    ...

def constrained_isinstance(obj: Any, cls_or_types: Type[T] | tuple[Type[Any], ...]) -> bool:
    # 你的实际性能优化实现
    if isinstance(cls_or_types, tuple):
        return any(isinstance(obj, t) for t in cls_or_types)
    return isinstance(obj, cls_or_types)

为什么之前的写法出错

你之前的代码中,tuple[*T]会让mypy将元组元素推断为类型本身(比如Type[Dog]、Type[Cat]),而非这些类型对应的实例类型。通过tuple[Type[Unpack[Ts]]],我们明确告诉类型检查器:元组里的每个元素都是某个实例类型的Type对象,最终返回的TypeGuard会对应这些实例类型的联合(Union[Dog, Cat]),完全匹配内置isinstance的类型收窄行为。

兼容性说明

  • 如果使用Python 3.11+,可以直接从typing导入TypeVarTuple和Unpack,无需依赖typing_extensions。
  • 这个方案不需要依赖存根文件的临时写法,类型检查逻辑完全内联在函数签名中,更符合类型规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 05:17:02