如何为泛型类中的受限方法添加类型提示?
泛型类方法的子集类型约束实现
我有一个仅适用于泛型类受限子集的Python方法。举个构造示例,希望以下代码中的Spam.floatify仅对Spam[int]实例可用,同时允许Spam[str]实例存在:
class Spam[T]: def __init__(self, ham: T) -> None: self.ham: T = ham def floatify(self) -> float: return float(self.ham) # 对int实例没问题,但str实例调用时本该报错却没报 Spam(0).floatify() Spam("eggs") Spam("eggs").floatify() # 此处应该触发类型检查错误,但当前代码不会
解决方案
要实现这种仅针对特定泛型参数子集开放方法的类型约束,有两种简单可行的方式:
方案一:用Self限定方法的可用实例类型
通过给floatify方法的self参数指定Self[int]类型,直接让类型检查器明确:只有Spam[int]实例才能调用该方法。
from typing import Generic, Self, TypeVar T = TypeVar('T') class Spam(Generic[T]): def __init__(self, ham: T) -> None: self.ham: T = ham def floatify(self: Self[int]) -> float: return float(self.ham) # 合法:Spam[int]可以调用floatify Spam(0).floatify() # 合法:允许实例化Spam[str] Spam("eggs") # 类型检查器报错:Spam[str]不存在floatify方法 Spam("eggs").floatify()
方案二:重载泛型类定义
利用@overload专门为Spam[int]声明包含floatify方法的类结构,类型检查器会以重载声明为准,限制方法的调用范围。
from typing import Generic, TypeVar, overload T = TypeVar('T') # 重载声明:只有Spam[int]拥有floatify方法 @overload class Spam[int]: def floatify(self) -> float: ... class Spam(Generic[T]): def __init__(self, ham: T) -> None: self.ham: T = ham def floatify(self) -> float: return float(self.ham) # 合法调用 Spam(0).floatify() # 合法实例化 Spam("eggs") # 类型检查器报错:Spam[str]无floatify方法 Spam("eggs").floatify()
以上两种方案都能被Mypy、Pyright等主流类型检查器识别,既保证Spam[int]可以正常使用floatify,又能拦截其他泛型实例对该方法的非法调用。
内容的提问来源于stack exchange,提问作者Anerdw
相关产品推荐
相关产品推荐

