Как объявить, что сама функция имеет определенный тип?
Скажем, у меня есть функция, которая принимает другие функции в качестве аргументов:
Metric = Callable[List[float], float]
def metric_doubler(metric: Metric, lst: List[float]):
return 2*metric(lst)
И я хочу написать другие функции и объявить, что они имеют тип Metric
например,
def my_mean(lst: List[float]) -> float:
return sum(lst)/len(lst)
Есть ли способ утверждать, что my_mean
в этом случае имеет тип Metric
? В частности, реальный случай использования - это когда у меня много таких функций, и я хочу ловить ошибки, если мне нужно изменить тип Metric
,
1 ответ
На самом деле я не думаю, что это то, что необходимо явно проверять - просто напишите свой код как обычно и постоянно запускайте mypy против него.
Если вы случайно обнаружите несоответствие при рефакторинге некоторого кода, mypy сообщит вам об этих несоответствиях.
Итак, если у вас есть код, который делает metric_doubler(my_mean, something)
и изменить определение Metric
без изменения my_mean
Mypy будет жаловаться на вызов этой функции.
(Это одно из преимуществ статической типизации. Если все набрано, вы можете более бесстрашно проводить рефакторинг, поскольку ваши инструменты могут выявлять для вас ошибки и несоответствия - вам часто не нужно выполнять какую-либо дополнительную работу, кроме добавления типов.)
Если вы хотите быть абсолютно уверенным, что все совпадает, вы можете добавить несколько дополнительных юнит-тестов. Например, возможно, добавьте модульный тест, который выглядит так
def test_my_mean() -> None:
assert metric_doubler(my_mean, something) == something_else
Затем запустите mypy как для полной базы кода, так и для ваших тестов.
Или еще проще:
def expects_metric(x: Metric) -> None: pass
def test_my_mean() -> None:
expect_metric(my_mean)
Я думаю, что первая форма (где вы связываете проверку во время выполнения вместе со статическими проверками) более полезна.