Как задать тип возвращаемого значения функции, зависящий от типа входного аргумента?
Проблема с типами в функции маппинга данных для Postgres в Python
У меня есть функция, которая конвертирует типы данных Python в типы данных Postgres следующим образом:
def map_type(input):
if isinstance(input, int):
return MyEnum(input)
elif isinstance(input, str):
return MyCustomClass(str)
Я мог бы указать намек на тип для этой функции так:
def map_type(input: Union[int, str]) -> Union[MyEnum, MyCustomClass]: ...
Однако тогда код, который выглядит следующим образом, не пройдет проверку типов, хотя он корректен:
myvar = map_type('foobar')
print(myvar.property_of_my_custom_class)
Вот полный пример (рабочий код, но с ошибками в аннотации типов):
from typing import Union
from enum import Enum
class MyEnum(Enum):
VALUE_1 = 1
VALUE_2 = 2
class MyCustomClass:
def __init__(self, value: str) -> None:
self.value = value
@property
def myproperty(self) -> str:
return 2 * self.value
def map_type(value: Union[int, str]) -> Union[MyEnum, MyCustomClass]:
if isinstance(value, int):
return MyEnum(value)
elif isinstance(value, str):
return MyCustomClass(value)
raise TypeError('Invalid input type')
myvar1 = map_type(1)
print(myvar1.value, myvar1.name)
myvar2 = map_type('foobar')
print(myvar2.myproperty)
Я понимаю, что мог бы разделить маппинг на две функции, но цель состоит в том, чтобы иметь универсальную функцию для преобразования типов.
Также я задумался о работе с классами и полиморфизмом, но тогда как мне аннотировать методы верхнего класса? Поскольку их выходной тип будет зависеть от конкретного типа экземпляра.
Как лучше всего решить данную проблему с типами?
1 ответ(ов)
Для выходных типов, которые идентичны или являются вариацией входного типа, вы можете использовать следующую стратегию (и избежать необходимости добавления дополнительных @overload
при введении/поддержке новых типов):
from typing import TypeVar
T = TypeVar("T") # имя переменной должно совпадать со строкой
def filter_category(category: T) -> list[T]:
# предположим, что get_options() — это функция,
# которая получает произвольное количество объектов различных типов
return [
option
for option in get_options()
if isinstance(option, category) # исправлено на isinstance
]
Функция filter_category
будет правильно ассоциироваться как с вашим IDE (например, VSCode, PyCharm и т.д.), так и со статическим анализатором типов (таким как Mypy):
# например, list_of_ints будет показан в вашем IDE как тип list[Type[int]]
list_of_ints = filter_category(int)
# или здесь list_of_bools будет показан в вашем IDE как тип list[Type[bool]]
list_of_bools = filter_category(bool)
Примечание: это не охватывает все аспекты вопроса, только его подмножество, хотя и очень распространенное.
Как указать несколько типов возвращаемых значений с помощью аннотаций типов
Можно ли опустить Optional, если я установил значение по умолчанию на None?
Как изменить порядок столбцов в DataFrame?
'pip' не распознан как командa внутреннего или внешнего формата
Почему statistics.mean() работает так медленно?