У меня есть следующая функция:
T = TypeVar("T")
def handle_func(x: int, func: Callable[[int], T]) -> T:
return func(x)
и я могу использовать его так:
handle_func(1, lambda x: x + 1)
handle_func(1, lambda x: x == 1)
Когда я запускаю mypy, все хорошо.
Но как я могу добавить значение по умолчанию для func
?
Когда я это делаю:
def handle_func(x: int, func: Callable[[int], T] = lambda x: x + 1) -> T:
return func(x)
и запустите mypy, я получу:
error: Incompatible default for argument "func" (default has type "Callable[[int], int]", argument has type "Callable[[int], T]") [assignment]
error: Incompatible return value type (got "int", expected "T") [return-value]
Как мне это напечатать? Что я понимаю неправильно?
Один из способов справиться с этим — разделить две формы:
int
(не общий); иT
).Вы можете сделать это как перегрузки:
from typing import Callable, overload, TypeVar
T = TypeVar("T")
@overload
def handle_func(x: int) -> int:
...
@overload
def handle_func(x: int, func: Callable[[int], T]) -> T:
...
def handle_func(x, func = lambda x: x + 1):
return func(x)
Можете ли вы объяснить, почему первое определение перегрузки будет без второго аргумента?
@Meir, потому что, как объяснялось перед фрагментом, это форма, в которой вы передаете один аргумент x
(и, следовательно, используете значение по умолчанию func
).
Это решение, рекомендованное для проблемы GitHub: github.com/python/mypy/issues/3737#issuecomment-316263133.
Проверка типов просто жалуется, что неперегруженный handle_func
не набирается. Как мне тоже это напечатать?
Я решил это, набрав неперегруженный более общий тип (Callable и return Any).
Один из подходов — просто привести значение по умолчанию:
def handle_func(
x: int,
func: Callable[[int], T] = cast(Callable[[int], T], lambda x: x + 1)
) -> T:
return func(x)
Демо с mypy: https://mypy-play.net/?mypy=latest&python=3.12&gist=b840e26f46173e646cab2fd08e266c79
В общем, я стараюсь избегать использования cast
, поскольку это просто заставляет проверку типов «доверять» мне и потенциально приводит к ошибкам.
Да, но прискорбным фактом является то, что вы не можете аннотировать лямбда-функцию с помощью текущей системы типизации, а решение @jonrsharpe также не помогает типизировать проверку вызываемого значения по умолчанию (например, оно не жалуется, если вы делаете lambda x, y: x + 1
значение по умолчанию), так что вы также можете cast
использовать значение, которое сделает mypy счастливым.
Я думаю, что у меня здесь было две проблемы: первая - это универсальный вариант по умолчанию, и для этого я принял первый ответ, а также проблема с вводом лямбда-функций, которую решает ваше приведение.
Отвечает ли это на ваш вопрос? Функция аннотирования с помощью TypeVar и значения по умолчанию приводит к типу объединения