Python子类继承场景下typing返回值类型标注不兼容问题求解
报错原因
静态类型检查器不会根据运行时传入的参数值推导函数返回的具体子类类型:
- 当
method_body返回类型标注为ParentClass时,检查器默认返回的是父类实例,无法确定它是ChildA的子类实例 - 当你把返回类型改为
Union[ChildA, ChildB]时,检查器只知道返回值是两个子类的其中一种,依旧无法匹配another_method要求的ChildA固定返回类型
解决方案
方案1:使用@overload重载函数签名(最推荐)
通过重载明确标注不同入参对应的返回类型,类型检查器会直接匹配对应的重载规则:
from typing import Union, overload, Literal class ParentClass: parent_prop = 1 class ChildA(ParentClass): child_a_prop = 2 class ChildB(ParentClass): child_b_prop = 3 @overload def method_body(val: Literal[True]) -> ChildA: ... @overload def method_body(val: Literal[False]) -> ChildB: ... def method_body(val: bool) -> Union[ChildA, ChildB]: if val: return ChildA() else: return ChildB() def another_method() -> ChildA: return method_body(True) print(another_method().child_a_prop)
提示:如果使用Python 3.8以下版本,
Literal需要从typing_extensions第三方库导入。
方案2:使用cast强制声明类型
如果你100%确定当前逻辑下method_body(True)一定返回ChildA实例,可以用cast直接告诉类型检查器忽略自动推导,直接认定目标类型:
from typing import Union, cast # 类定义和原代码一致,此处省略 def method_body(val: bool) -> Union[ChildA, ChildB]: if val: return ChildA() else: return ChildB() def another_method() -> ChildA: return cast(ChildA, method_body(True))
方案3:添加运行时类型检查窄化类型
通过isinstance判断让类型检查器自动窄化类型,这种方式同时兼顾了运行时的类型安全:
from typing import Union # 类定义、method_body定义和方案2一致,此处省略 def another_method() -> ChildA: res = method_body(True) if isinstance(res, ChildA): return res raise TypeError("调用method_body(True)未返回预期的ChildA实例")
内容的提问来源于stack exchange,提问作者Aghil Varghese
相关产品推荐
相关产品推荐

