Python 为子类的实例键入签名?

Python typing signature for instance of subclass?

考虑:

from __future__ import annotations

class A:
    @classmethod
    def get(cls) -> A:
        return cls()

class B(A):
    pass

def func() -> B: # Line 12
    return B.get()

运行 mypy 我们得到:

$ mypy test.py
test.py:12: error: Incompatible return value type (got "A", expected "B")
Found 1 error in 1 file (checked 1 source file)

此外,我检查了旧式递归注释是否有效。即:

# from __future__ import annotations

class A:
    @classmethod
    def get(cls) -> "A":
# ...

...无济于事。

当然可以:

from typing import cast

def func() -> B: # Line 12
    return cast(B, B.get())

每次都会弹出这个案例。但我想避免这样做。

应该如何输入?

clsself参数通常由mpyp推断,以避免大量冗余代码,但需要时可以通过注解显式指定。

在这种情况下,class 方法的显式类型如下所示:

class A:
    @classmethod
    def get(cls: Type[A]) -> A:
        return cls()

所以我们在这里真正需要的是一种使 Type[A] 成为通用参数的方法,这样当 class 方法被子 class 调用时,您可以引用child class 代替。幸运的是,我们有 TypeVar 个值。

将其应用到您现有的示例中,我们将得到以下内容:

from __future__ import annotations

from typing import TypeVar, Type


T = TypeVar('T')


class A:
    @classmethod
    def get(cls: Type[T]) -> T:
        return cls()


class B(A):
    pass


def func() -> B:
    return B.get()

现在 mypy 应该又是你的朋友了!