是否有任何方法可以键入抽象父类方法,以便知道子类方法返回自身,而不是抽象父类。
class Parent(ABC):
@abstractmethod
def method(self) -> [what to hint here]:
pass
class Child1(Parent)
def method(self):
pass
def other_method(self):
pass
class GrandChild1(Child1)
def other_method_2(self):
pass
这更多是为了改进 PyCharm 或 VScode 的 python 插件等 IDE 的自动完成功能。
所以,文档中描述了一般方法这里
import typing
from abc import ABC, abstractmethod
T = typing.TypeVar('T', bound='Parent') # use string
class Parent(ABC):
@abstractmethod
def method(self: T) -> T:
...
class Child1(Parent):
def method(self: T) -> T:
return self
def other_method(self):
pass
class GrandChild1(Child1):
def other_method_2(self):
pass
reveal_type(Child1().method())
reveal_type(GrandChild1().method())
mypy
给我们:
test_typing.py:22: note: Revealed type is 'test_typing.Child1*'
test_typing.py:23: note: Revealed type is 'test_typing.GrandChild1*'
注意,我不得不继续使用类型变量来让它工作,所以当我最初尝试在子类注释中使用实际的子类时,它(错误地?)继承了孙子中的类型:
class Child1(Parent):
def method(self) -> Child1:
return self
我会得到 mypy:
test_typing.py:22: note: Revealed type is 'test_typing.Child1'
test_typing.py:23: note: Revealed type is 'test_typing.Child1'
同样,我不确定这是否是预期/正确的行为。 mypy 文档 目前有一个警告:
此功能是实验性的。使用类型注释检查代码 self arguments 仍未完全实施。 Mypy 可能不允许有效 代码或允许不安全的代码。
Python 3.11 在PEP-0673 的基础上引入了更优雅的解决方案,预定义类型
Self
(official docs)。例子:
from typing import Self
class Parent(ABC):
@abstractmethod
def method(self) -> Self:
pass
class Child1(Parent)
def method(self) -> Self:
pass
def other_method(self) -> Self:
pass
class GrandChild1(Child1)
def other_method_2(self) -> Self:
pass
它也涵盖了类方法:
class Shape:
@classmethod
def from_config(cls, config: dict[str, float]) -> Self:
return cls(config["scale"])
注意:对于 pre-python-3.11 可以使用:
1 - 引用类型,例如
class Parent:
def method(self) -> "Parent":
pass
2 - 或延迟类型提示评估(PEP-0563,或其他SO答案,python 3.7+):
from __future__ import annotations
class Parent:
def method(self) -> Parent:
pass