Строка, всплывающая подсказка, одна строка текста

Я изначально собирался оставить это в комментарии, но мой ответ стал немного длинным, поэтому вот оно ...

Для MutableMapping можно указать только два параметра: _KT и _VT. Этот дополнительный параметр _T остается неуказанным. Как проверяет тип этого третьего типа ...?

Поскольку в основном @jonrsharpe _T, не параметр типа класса, это параметр типа функции. В основном, когда вы вызываете этот метод, mypy будет иметь:

  1. Уже привязанные _KT и _VT к другому типу. Итак, если мы сделаем foo: MutableMapping[str, int] = ..., тогда позвоним foo.pop(...), mypy поймет, что _KT и _VT привязаны к str и int соответственно в момент, когда мы вызываем pop.
  2. Mypy дополнительно замечает, что у нас есть свободный (параметр aka unbound ), плавающий вокруг, если мы вызываем вторую перегрузку. Затем он попытается вывести , какой правильный тип _T основан на любом значении, которое мы передаем в / окружающем контексте. Например, предположим, что я foo.pop("x", "bar"). Это соответствует второй перегрузке. Мы также ранее говорили, что _KT и _VT связаны с str и int соответственно. Затем Мига замечает, что _T несвязана и пытается вывести соответствующий тип. Здесь мы знаем, что значение, которое мы передаем, имеет тип «str» и что тип параметра Union[int, _T] (после подстановки в связанных типах). Мы также знаем, что значение, которое мы передаем, должно быть подтипом параметров - мы знаем, что str должен быть подтипом Union[int, _T]. Затем Mypy запускает алгоритм вывода с использованием всех вышеперечисленных сведений / всех известных ограничений и в этом случае может сделать вывод, что _T должен иметь тип str.

( В качестве побочного примечания алгоритм вывода алгоритма Mpy здесь не идеален. Иногда он может вывести правильный тип, если выражение особенно сложно / в настоящее время неправильно обрабатывает некоторые случаи краев.)

Если вы хотите получить более подробное описание того, как работает алгоритм вывода типа mypy, вы можете попробовать spelunking через кодовую базу mypy. В частности, mypy вызывает эту функцию , которая в свою очередь вызывает здесь код . Справедливое предупреждение, это немного сложно понять.

В этом контексте ковариант возвращаемого типа _T ...?

Мы знаем здесь, что _KT, _VT и _T все инварианты, основанные на их определении .

Каждая из трех переменных типа может быть полностью независимой друг от друга. Это соответствует поведению runtime: если у меня есть Dict[str, str], то выполнение my_dict.pop("x", 4) может вернуть какую-либо строку или число 4 в зависимости от того, что именно содержит my_dict.

Имеет ли тип возврата должны быть того же типа, что и по умолчанию, или только совместимого подтипа?

. Таким образом, полностью исключая генерики, вот (упрощенные) правила перегрузки с mypy 0.620. (В старых версиях mypy использовался аналогичный, но более пушистый, ad-hoc алгоритм).

  1. По умолчанию mypy позволит полностью возвращать типы возвращаемых двух перегрузок: им не нужно чтобы иметь какое-либо неотъемлемое отношение друг к другу.
  2. Mypy, однако, запретит неотъемлемо небезопасные определения перегрузки. Два варианта перегрузки считаются небезопасными, если: все аргументы первого варианта совместимы со вторым. Тип возврата первого варианта не совместим с (например, не подтипом) второго. В конкретном случае pop аргументы первого варианта действительно совместимы со вторым: по какой-либо причине аргумент default помечен как необязательный. Это означает, что вызов foo.pop("x") может фактически соответствовать обеим перегрузкам. Однако первый тип возврата первого варианта варианта перегрузки является подтипом второго: _VT является подтипом Union[_VT, _T], независимо от того, что заканчивается _T.
  3. Когда вы на самом деле вызываете перегрузку, mypy проверяет доступные перегрузки в том порядке, в котором они определены, и использует первый вариант, который соответствует. Чтобы убедиться, что этот алгоритм работает так, как ожидалось, mypy сообщит об ошибке, если перегрузки определены таким образом, что невозможно, чтобы некоторые варианты были сопоставлены.

Эти правила не действительно изменяются значительным образом, если мы добавим дженерики в микс.

В документации есть более подробные сведения / дополнительные примеры о нюансах перегрузки функций .

0
задан Peter 19 January 2019 в 07:58
поделиться