Как объявить, что сама функция имеет определенный тип?

Скажем, у меня есть функция, которая принимает другие функции в качестве аргументов:

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_meanMypy будет жаловаться на вызов этой функции.

(Это одно из преимуществ статической типизации. Если все набрано, вы можете более бесстрашно проводить рефакторинг, поскольку ваши инструменты могут выявлять для вас ошибки и несоответствия - вам часто не нужно выполнять какую-либо дополнительную работу, кроме добавления типов.)

Если вы хотите быть абсолютно уверенным, что все совпадает, вы можете добавить несколько дополнительных юнит-тестов. Например, возможно, добавьте модульный тест, который выглядит так

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)

Я думаю, что первая форма (где вы связываете проверку во время выполнения вместе со статическими проверками) более полезна.

Другие вопросы по тегам