Задать вопрос
AleksVersus
@AleksVersus
графоман

Как правильно определять изменяющиеся типы полей при наследовании классов в python?

Я не особо сведущ в программировании, любительствую. Различные ИИ-шки начали меня путать, поэтому вопрос к знатокам. Есть родительский класс с полями и методами (код упрощён):
class ParFolder:
  def __init__(self, path:str) -> None:
      self.folders:list[ParFolder] = []
      self.files:list[ParFile] = []
      for p in os.listdir(path):
          if os.path.isdir(p): self.folders.append(ParFolder(p))
          if os.path.isfile(p): self.files.append(ParFile(p))

Есть класс, наследуемый от родительского. В нём полностью переопределён init, super не используется, но используются те же самые поля, но в этих полях должны храниться уже данные других типов. Опять же код упрощён:
class ChildFolder(ParFolder):
  def __init__(self, path:str) -> None:
      self.folders:list[ChildFolder] = []
      self.files:list[ChildFile] = []
      for p in os.listdir(path):
          if os.path.isdir(p): self.folders.append(ChildrFolder(p))
          if os.path.isfile(p): self.files.append(ChildFile(p))


В методе конструктора мне нужно использовать для дочернего класса свои типы, отличные от родительского. Мне нужно, чтобы дочерний унаследовал все методы от родительского.

С точки зрения интерпретатора никаких проблем нет. Динамическая типизация, код отлично выполняется, всё работает. Проблема в реакции линтера на переопределение типов полей в дочернем классе. Пробовал решить через Дженерики, но это приводит к усложнению кода, необходимости передавать класс в конструктор и т.д.

Может вопрос очень лёгкий, может это решается каким-то архитектурным паттерном, но я уже неделю ничего не могу найти и не знаю, куда копать. Сложность ставлю среднюю.

Как правильно переопределить типы полей дочернего класса, чтобы линтер понимал, где какие данные должны использоваться?
  • Вопрос задан
  • 25 просмотров
Подписаться 1 Средний 4 комментария
Помогут разобраться в теме Все курсы
  • Нетология
    Python-разработчик: расширенный курс + нейросети
    12 месяцев
    Далее
  • Академия Эдюсон
    Python-разработчик + ИИ
    9 месяцев
    Далее
  • ProductStar × РБК
    Профессия: Python-разработчик + ИИ
    8 месяцев
    Далее
Пригласить эксперта
Ответы на вопрос 1
opium
@opium
Просто люблю качественно работать
линтер прав: list инвариантен, сужение list[ParFile] до list[ChildFile] в наследнике ломает контракт родителя.

сделай сам ParFolder generic-классом, создание файла вынеси в отдельный метод:

class ParFolder(Generic[FileT]):
    def __init__(self, path):
        self.folders: list[Self] = []
        self.files: list[FileT] = []
    def make_file(self, path) -> FileT: return ParFile(path)

class ChildFolder(ParFolder[ChildFile]):
    def make_file(self, path) -> ChildFile: return ChildFile(path)


ChildFolder буквально наследует ParFolder, files параметризован ChildFile, folders через Self сам подставляет ChildFolder. mypy это реально ловит.

p.s. Self с 3.11, для старых версий typing_extensions.Self
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы