注解在mixin中返回self的方法的返回类型

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

[我使用的是构建器模式,其中(大)类上的大多数方法都返回其标识(self),并因此被注释为返回它们所属的类的类型:

class TextBuilder:
    parts: List[str]           # omitted
    render: Callable[[], str]  # for brevity

    def text(self, val: str) -> "TextBuilder":
        self.parts.append(val)
        return self

    def bold(self, val: str) -> "TextBuilder":
        self.parts.append(f"<b>{val}</b>")
        return self

    ...

示例用法:

joined_text = TextBuilder().text("a ").bold("bold").text(" text").render()  
# a <b>bold</b> text

现在,随着此类的增长,我想将相关的方法拆分并分组为mixin:

class BaseBuilder:
    parts: List[str]           # omitted
    render: Callable[[], str]  # for brevity


class TextBuilder(BaseBuilder):
    def text(self, val: str):
        self.parts.append(val)
        return self
    ...


class HtmlBuilder(BaseBuilder):
    def bold(self, val: str):
        self.parts.append(f"<b>{val}</b>")
        return self
    ...


class FinalBuilder(TextBuilder, HtmlBuilder):
    pass

但是,我看不到一种以正确的方式注释mixin类的返回类型的方法,即所产生的类FinalBuilder始终使mypy相信它返回FinalBuilder而不是其中一个mixin类。所有这些当然都假设我想actually注释self并返回类型,因为它们可能无法从这些方法内部发生的事情中推断出来。

我已经尝试使mixin类成为通用类,并明确地将它们标记为返回绑定到T的类型BaseBuilder,但这不满足mypy的要求。有任何想法吗?现在,我只是跳过所有这些恶作剧,并在各处省略返回类型,因为在使用FinalBuilder时应该正确地推断出它们的返回类型,但是我仍然对是否有一种通用的方法感到好奇。

我正在使用一个构建器模式,其中(大)类上的大多数方法都返回其标识(自身),并因此被注释为返回其所属类的类型:class TextBuilder:parts:...] >

python types annotations pycharm mypy
1个回答
1
投票

如果您希望返回类型始终是self,只需像这样注释self参数:

from typing import List, Callable, TypeVar

T = TypeVar('T', bound=BaseBuilder)

class BaseBuilder:
    parts: List[str]           # omitted
    render: Callable[[], str]  # for brevity


class TextBuilder(BaseBuilder):
    def text(self: T, val: str) -> T:
        self.parts.append(val)
        return self
    ...


class HtmlBuilder(BaseBuilder):
    def bold(self: T, val: str) -> T:
        self.parts.append(f"<b>{val}</b>")
        return self
    ...


class FinalBuilder(TextBuilder, HtmlBuilder):
    pass


# Type checks
f = FinalBuilder().text("foo").bold("bar")

# Mypy states this is type 'FinalBuilder'
reveal_type(f)
© www.soinside.com 2019 - 2024. All rights reserved.