类型提示子类返回自我

问题描述 投票:0回答:2

是否有任何方法可以键入抽象父类方法,以便知道子类方法返回自身,而不是抽象父类。

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 的自动完成功能。

python abstract-class type-hinting abc
2个回答
16
投票

所以,文档中描述了一般方法这里

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 可能不允许有效 代码或允许不安全的代码。


0
投票

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
© www.soinside.com 2019 - 2024. All rights reserved.