Типизация на Python: Создайте тип возвращаемого значения функции python на основе входных аргументов функции

#python #type-hinting #typing

Вопрос:

У меня есть функция, которая формирует список определенных экземпляров класса, допустим, это будет тип вывода list[SomeClass] .

Тип выходного класса может отличаться в зависимости от данных (например, это может быть list[ClassA] , list[ClassB] list[ClassC] , и т.д.).

Я пытаюсь передать этот список и лямбда — функцию в качестве аргументов в другой класс . Цель последнего класса состоит в том, чтобы разделить аргумент списка на два отдельных списка на основе этой лямбда-функции. Так что в основном то, что мне нужно, это:

 def func_A(cls_instance: some_cls) -gt; list[some_cls]:  .....  .....  return list[some_cls]  class DividerClass()  def __init__(list_of_classes: list[Object], func: Callable):  self.list_of_classes = list_of_classes  self.result_list_1 = []  self.result_list_2 = []      def divide():  for item in self.list_of_classes:  if func(item):  self.result_list_1.append(item)  else:  self.result_list_2.append(item)  return self.result_list_1, self.result_list_2  if __name__ == '__main__':  list_1 = func_A(SomeClass()) -gt; list[SomeClass]  list_2 = func_A(YetAnotherClass()) -gt; list[YetAnotherClass]  result_1_a, result_1_b = DividerClass(list_1, lambda_func).divide() -gt; tuple[list[SomeClass],list[SomeClass]]  resule_2_a, result_2_b = DividerClass(list_2, lambda_func).divide() -gt; tuple[list[YetAnotherClass],list[YetAnotherClass]]   

Но вместо того, чтобы получать такие результаты, как:

 -gt; tuple[list[SomeClass],list[SomeClass]] -gt; tuple[list[YetAnotherClass],list[YetAnotherClass]]  

У меня есть такой вывод:

 -gt; tuple[list, list] -gt; tuple[list, list]  

Итак, вопрос в том, как заставить компилятор/IDE знать тип класса внутри списка и выводить тип списка классов на основе входного аргумента?

Ответ №1:

Используется typing.Generic для указания того, что в различных подписях будет использоваться произвольный, но фиксированный тип.

Что-то вроде

 from typing import TypeVar, Tuple, Generic   T = TypeVar('T')  def func_A(cls_instance: T) -gt; list[T]:  ...   class DividerClass(Generic[T])  def __init__(self, list_of_classes: list[T], func: Callable[[T],list[T]]):  self.list_of_classes = list_of_classes  self.result_list_1 = []  self.result_list_2 = []  self.func = func    def divide(self) -gt; Tuple[list[T], list[T]]:  for item in self.list_of_classes:  if self.func(item):  self.result_list_1.append(item)  else:  self.result_list_2.append(item)  return self.result_list_1, self.result_list_2  

Комментарии:

1. Большое спасибо. Это, кажется, решает мою проблему. Но какова цель установки функции as Callable[[T],list[T]]) . Это что-нибудь меняет?

2. Callable само по себе означает , что вы могли бы передать что-то вроде lambda x, y: (x-y)/y , но это было бы несовместимо с тем, как self.func на самом деле вызывается .