Введите контрольный код с помощью mypy
:
def foo(a: str, b: float, c: int):
print(a, b, c + 1)
foo('ok', 2.2, 'bad')
показывает неверный вызов слишком foo
:
error: Argument 3 to "foo" has incompatible type "str"; expected "int"
Теперь предположим, что у нас есть оберточная функция, такая как:
from typing import Callable, Any
def say_hi_and_call(func: Callable[..., Any], *args):
print('Hi.')
func(*args)
и используйте недействительный вызов
say_hi_and_call(foo, 'ok', 2.2, 'bad')
mypy
не сообщит о каких-либо ошибках, вместо этого мы узнаем об этой ошибке во время выполнения:
TypeError: must be str, not int
Я хотел бы поймать эту ошибку раньше. Есть ли возможность уточнить аннотации типа таким образом, чтобы mypy
мог сообщить о проблеме?
ОК, единственное решение, которое я придумал, делает ясность функции явной, т.е.
from typing import Any, Callable, TypeVar
A = TypeVar('A')
B = TypeVar('B')
C = TypeVar('C')
def say_hi_and_call_ternary(func: Callable[[A, B, C], Any], a: A, b: B, c: C):
print('Hi.')
func(a, b, c)
def foo(a: str, b: float, c: int):
print(a, b, c + 1)
say_hi_and_call_ternary(foo, 'ok', 2.2, 'bad')
Конечно, нужно было бы использовать аналогичные say_hi_and_call_unary
и say_hi_and_call_binary
и т.д.
Но поскольку я ценю мое приложение, которое не взрывается в PROD по сравнению с некоторыми LOC, я счастлив, когда mypy
может сообщить об ошибке, что теперь, безусловно, имеет место:
error: Argument 1 to "say_hi_and_call_ternary" has incompatible type "Callable[[str, float, int], Any]"; expected "Callable[[str, float, str], Any]"