Python 重写子类中方法返回的类型提示,无需重新定义方法签名

Int*_*rer 5 python oop type-hinting method-signature

float我有一个基类,在方法的返回上有类型提示。

在子类中,在不重新定义签名的情况下,我可以以某种方式将方法返回的类型提示更新为 吗int


示例代码

#!/usr/bin/env python3.6


class SomeClass:
    """This class's some_method will return float."""

    RET_TYPE = float

    def some_method(self, some_input: str) -> float:
        return self.RET_TYPE(some_input)


class SomeChildClass(SomeClass):
    """This class's some_method will return int."""

    RET_TYPE = int


if __name__ == "__main__":
    ret: int = SomeChildClass().some_method("42"). # 
    ret2: float = SomeChildClass().some_method("42")
Run Code Online (Sandbox Code Playgroud)

我的 IDE 抱怨类型不匹配:

pycharm期望类型float

发生这种情况是因为我的 IDE 仍在使用SomeClass.some_method.


研究

我认为解决方案可能是使用泛型,但我不确定是否有更简单的方法。

Python:如何覆盖子类中实例属性的类型提示?

建议也许使用实例变量注释,但我不确定如何对返回类型执行此操作。

Int*_*rer 2

好的,所以我能够尝试并结合@AntonPomieshcheko@KevinLanguasco的答案,得出一个解决方案:

  • 我的 IDE (PyCharm) 可以正确推断返回类型
  • mypy报告类型是否不匹配
  • 即使类型提示指示不匹配,运行时也不会出错

这正是我想要的行为。非常感谢大家:)

#!/usr/bin/env python3

from typing import TypeVar, Generic, ClassVar, Callable


T = TypeVar("T", float, int)  # types supported


class SomeBaseClass(Generic[T]):
    """This base class's some_method will return a supported type."""

    RET_TYPE: ClassVar[Callable]

    def some_method(self, some_input: str) -> T:
        return self.RET_TYPE(some_input)


class SomeChildClass1(SomeBaseClass[float]):
    """This child class's some_method will return a float."""

    RET_TYPE = float


class SomeChildClass2(SomeBaseClass[int]):
    """This child class's some_method will return an int."""

    RET_TYPE = int


class SomeChildClass3(SomeBaseClass[complex]):
    """This child class's some_method will return a complex."""

    RET_TYPE = complex


if __name__ == "__main__":
    some_class_1_ret: float = SomeChildClass1().some_method("42")
    some_class_2_ret: int = SomeChildClass2().some_method("42")

    # PyCharm can infer this return is a complex.  However, running mypy on
    # this will report (this is desirable to me):
    # error: Value of type variable "T" of "SomeBaseClass" cannot be "complex"
    some_class_3_ret = SomeChildClass3().some_method("42")

    print(
        f"some_class_1_ret = {some_class_1_ret} of type {type(some_class_1_ret)}\n"
        f"some_class_2_ret = {some_class_2_ret} of type {type(some_class_2_ret)}\n"
        f"some_class_3_ret = {some_class_3_ret} of type {type(some_class_3_ret)}\n"
    )
Run Code Online (Sandbox Code Playgroud)

  • 如果它适合您的用例,那么这是可行的,但请注意,如果您想要有一个子类层次结构(如问题中所建议的),例如“class SomeChildClass2(SomeChildClass1):”,那么您基本上会回到开始的地方。 (2认同)