重载签名未强化前置条件却被mypy判定与父类不兼容?
背景
现有无法修改的父类A:
from typing import Optional class A: def foo(self, x: Optional[bool] = None) -> None: pass
编写子类B时,尝试仅通过typing.overload区分两种调用签名,未缩小参数类型:
# ... 导入A from typing import Literal, Optional, overload class B(A): @overload def foo(self, x: Literal[True]) -> None: ... @overload def foo(self, x: Optional[Literal[False]] = None) -> None: ... def foo(self, x: Optional[bool] = None) -> None: pass
问题现象
我认为B.foo的两个重载签名完全覆盖了A.foo的所有调用场景,且未缩小参数类型,并未违反里氏替换原则,但mypy却抛出错误:
error: Signature of "foo" incompatible with supertype "A" [override]
note: Superclass:
note: def foo(self, x: Optional[bool] = ...) -> None
note: Subclass:
note: @overload
note: def foo(self, x: Literal[True]) -> None
note: @overload
note: def foo(self, x: Optional[Literal[False]] = ...) -> None
PyCharm的类型检查也会报错,仅高亮第一个Literal[True]的重载签名,提示其与父类方法签名不匹配。
疑问
这是我忽略了某些类型检查规则,还是mypy的限制或BUG?
目前已找到相关的mypy issue(#14725、#14002、#3750),但暂无回应,暂时可以用# type: ignore[override]忽略该报错,但想了解是否存在禁止这种写法的合理原因。
内容的提问来源于stack exchange,提问作者Daniel Fainberg

