Как автоматически определить тип дочернего класса с помощью mypy (без использования приведения)

#python #class #type-inference #mypy

#питон #класс #вывод типа #майпи

Вопрос:

У меня есть универсальный класс ( Widget ) и подклассы с разными атрибутами. Я использую словарь, ключ которого является экземпляром этих подклассов в функции.

Как автоматически определить, с mpypy каким подклассом у меня есть?

Более конкретно, это код, который у меня есть:

 from dataclasses import dataclass from typing import ClassVar, Dict   @dataclass class Widget:  """Generic class for widget"""   @dataclass class Rectangle(Widget):  """A Color Rectangle"""   posx: int  posy: int  width: int = 500  height: int = 200  color: int = 0xFF0000   @dataclass class Button(Widget):  """A clickable button"""   posx: int  posy: int  width: int = 200  height: int = 100  label: str = "some label"   @dataclass class TestCase:  ID: ClassVar[int]  WIDGETS: ClassVar[Dict[str, Widget]]   class TestCaseButton(TestCase):  ID = 1  WIDGETS = {  "ref": Button(posx=0, posy=0, label="Click me!"),  }   class TestCaseRectangle(TestCase):  ID = 2  WIDGETS = {  "ref": Rectangle(posx=0, posy=0, color=0xFFFFFF),  "other": Button(posx=100, posy=100, label="DANGER!"),  }   def run_tc_button(tc: TestCase):  w = tc.WIDGETS["ref"]  print(w.label)   def run_tc_rectangle(tc: TestCase):  w = tc.WIDGETS["ref"]  print(w.color)   if __name__ == "__main__":  run_tc_button(TestCaseButton())  run_tc_rectangle(TestCaseRectangle())  

Проверка с mypy вернет следующее:

 mypy_infer.py:55: error: "Widget" has no attribute "label"  print(w.label)  ^ mypy_infer.py:60: error: "Widget" has no attribute "color"  print(w.color)  ^ Found 2 errors in 1 file (checked 1 source file)  

Я знаю, что мог cast бы использовать это для удаления ошибок:

 from dataclasses import dataclass from typing import ClassVar, Dict, cast  ...  def run_tc_button(tc: TestCase):  w = cast(Button, tc.WIDGETS["ref"])  print(w.label)   def run_tc_rectangle(tc: TestCase):  w = cast(Rectangle, tc.WIDGETS["ref"])  print(w.color)  ...  

… но я нахожу, что это немного тяжело использовать cast каждый раз в моих функциях.

Как я мог бы заставить функцию автоматически определять тип на основе значений в словаре?

Примечание: имена ключей не исправлены, поэтому a TypedDict , вероятно, не решит проблему.