Python为子类实例键入签名



考虑:

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 A:
@classmethod
def get(cls: Type[A]) -> A:
return cls()

因此,我们真正需要的是一种使Type[A]成为泛型参数的方法,这样,当从子类调用类方法时,您可以引用子类。幸运的是,我们有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应该又是你的朋友了!😎

最新更新