Python类型:注释父类返回子类类型对象的最佳方式

wru*_*esh 8 python mypy python-typing

我有一个如下的基类:

class BaseClass:
    @classmethod
    def create(cls, arg1: str) -> BaseClass:
        instance = cls(arg1)
        return instance
Run Code Online (Sandbox Code Playgroud)

还有一个像这样的派生类:

class DerivedClass(BaseClass):
    def __init__(self, arg: str) -> None:
        self.arg = arg 
Run Code Online (Sandbox Code Playgroud)

现在当我这样做时

data: DerivedClass = DerivedClass.create('first arg)
Run Code Online (Sandbox Code Playgroud)

mypy 给出以下错误:

"BaseClass" cannot be assigned to declared type "DerivedClass"
"BaseClass" is incompatible with "DerivedClass"
Run Code Online (Sandbox Code Playgroud)

我如何解决它是通过使用typing.cast

data: DerivedClass = cast(
    DerivedClass, 
    DerivedClass.get(derived_class_instance)
)
Run Code Online (Sandbox Code Playgroud)

我应该如何解决它而不使用typing.cast

Mar*_*hac 7

你可以改成BaseClass这样:

T = TypeVar("T")

from typing import TypeVar, Type

class BaseClass:
    @classmethod
    def get(cls: Type[T], instance: T) -> T:
        return instance
Run Code Online (Sandbox Code Playgroud)

这强制instance成为get正在调用的类方法的类型。所以BaseClass.get接受 aBaseClass并返回 a BaseClass,而DerivedClass.get接受 aDerivedClass并返回 a DerivedClass。运行mypy结果为:

Success: no issues found in 1 source file
Run Code Online (Sandbox Code Playgroud)