如何为接受ABC及子类类型的方法添加正确的类型提示?
解决方案
要解决传入抽象基类Transaction时mypy的报错问题,你可以通过调整TypeVar的定义方式,并使用typing.Type替代原生type来声明类型参数,具体实现如下:
from abc import ABC from typing import Collection, TypeVar, Type, List class Transaction(ABC): uuid: str class CashTransaction(Transaction): pass class SecurityTransaction(Transaction): pass # 用bound约束TypeVar,允许所有Transaction的子类(包括自身) TransactionType = TypeVar("TransactionType", bound=Transaction) class RecordKeeper: def __init__(self): self._transactions: List[Transaction] = [] def get_transactions( self, uuids: Collection[str], type_: Type[TransactionType], # 使用Type[T]支持抽象类的类型对象 ) -> List[TransactionType]: """Returns a list of Transactions matching uuids, ensuring they are all of type 'type_'.""" filtered = [] for tx in self._transactions: if tx.uuid in uuids and isinstance(tx, type_): filtered.append(tx) return filtered # 所有调用场景均能通过mypy检查 uuids = ["1", "2"] keeper = RecordKeeper() cash_transactions = keeper.get_transactions(uuids, CashTransaction) # 推断为List[CashTransaction] security_transactions = keeper.get_transactions(uuids, SecurityTransaction) # 推断为List[SecurityTransaction] any_transactions = keeper.get_transactions(uuids, Transaction) # 推断为List[Transaction],无mypy报错
为什么原来的实现会报错?
- 你之前显式枚举TypeVar的取值范围(
Transaction, CashTransaction, SecurityTransaction),当传入抽象类Transaction时,type[TransactionType]等价于type[Transaction],而mypy默认认为type[T]仅接受具体类的类型对象,因此抛出Only concrete class can be given错误。 - 使用
typing.Type[T]替代原生type[T]后,mypy会允许传递抽象类的类型对象,因为Type[T]的设计就是为了兼容抽象基类的类型引用。 - 改用
bound=Transaction约束TypeVar,既保留了类型推断的准确性(返回值会匹配传入的类型),又避免了显式枚举类型带来的冗余和冲突。
关于重载冲突的说明
你之前尝试重载时出现的Overloaded function signatures overlap错误,是因为重载的签名存在包含关系(比如CashTransaction是Transaction的子类),mypy无法区分不同重载分支的匹配逻辑。使用带bound的TypeVar可以用单一方法实现所有类型的兼容,无需重载。
内容的提问来源于stack exchange,提问作者Jakub Franek
相关产品推荐
相关产品推荐

