Я использую шаблон построителя, в котором большинство методов в (большом) классе возвращают свою идентичность (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
Теперь, когда этот класс растет, я хотел бы разделить и сгруппировать связанные методы в миксины:
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
Однако я не вижу способ правильно аннотировать возвращаемые типы классов миксинов таким образом, чтобы результирующий класс FinalBuilder
всегда заставлял mypy полагать, что он возвращает FinalBuilder
, а не один из классов миксинов. Все это, конечно, предполагает, что я хочу на самом деле аннотировать self
и возвращаемые типы, потому что они не могут быть выведены из того, что происходит внутри этих методов. c и явно помечая их как возвращающие тип T
, связанный с BaseBuilder
, но это не удовлетворило mypy. Любые идеи? На данный момент я просто собираюсь пропустить все эти махинации и опустить типы возвращаемых значений везде, так как они должны быть правильно выведены при использовании FinalBuilder
, но мне все еще любопытно, есть ли общий способ подойти к этому.