Недавно я начал использовать подсказки типов в своем коде и до сих пор обнаружил, что они быть (в основном) очень полезным.
Однако одна вещь, которая мне действительно не нравится, — это синтаксис, заставляющий средство проверки типов предполагать, что переменная имеет определенный тип. Учитывая этот пример:
import itertools
from typing import Iterable, Tuple
x: Iterable[Tuple[str, str]] = itertools.combinations('abc', 2)
# error: Incompatible types in assignment (expression has type "Iterable[Tuple[str, ...]]", variable has type "List[Tuple[str, str]]")
Насколько я могу судить, рекомендуемый способ обойти это — явно cast
объект, чтобы заставить средство проверки типов использовать указанный тип, например:
import itertools
from typing import Iterable, Tuple, cast
x = cast(Iterable[Tuple[str, str]], itertools.combinations('abc', 2))
Я лично нахожу это решение немного грубым. Меня в первую очередь беспокоит то, что неопытному читателю не ясно, что cast
существует исключительно для помощи статическому анализатору. (Если бы я еще не знал, я бы предположил, основываясь на имени и контексте, что он преобразует и делает копию в объект указанного типа, когда на самом деле нет затрат времени выполнения.)
cast
выглядит как любой старый вызов функции. Когда я вижу, что функция вызывается для значения, я ожидаю, что значение будет видоизменено и/или возникнут какие-то другие побочные эффекты, но в этом случае единственным побочным эффектом является то, что mypy
перестает жаловаться. Подсказки типов сами по себе имеют особый синтаксис, но я чувствую, что это размывает границы смесью нового синтаксиса ввода и традиционного синтаксиса Python. (Это уже немного размыто, так как вы должны import
типы и можете их компоновать, но это другой разговор.)
Есть ли альтернативный синтаксис для поведения, подобного cast
? Я ничего не нашел, но я надеялся на что-то вроде:
x1 = itertools.combinations('abc', 2)) # cast: Iterable[Tuple[str, str]]
x2: Iterable[Tuple[str, str]] = itertools.combinations('abc', 2)) # type: cast
x3: Cast[Iterable[Tuple[str, str]]] = itertools.combinations('abc', 2))
mypy
- person juanpa.arrivillaga   schedule 01.04.2019cast
предполагает, что оно ничего не делает, кроме как возвращает одно и то же значение. Я также сомневаюсь, что неопытный пользователь споткнется о это в отношении подсказки типа. - person chepner   schedule 01.04.2019mypy
поставляется сtypeshed
, который включает определение дляitertools.combinations
а>. Это немного неправильно (он объявляет егоIterable
, а неIterator
), но в любом случае это соответствует вашему объявлению. - person ShadowRanger   schedule 01.04.2019typeshed
должен объявлять все, что связано сproduct
,permutations
иcombinations
, какIterator
s; это ошибка, чтоcombinations
иcombinations_with_replacement
объявлены какIterable
s (product
/permutations
правильно объявлены какIterator
s). - person ShadowRanger   schedule 01.04.2019Tuple[str, str]
вместоTuple[str, ...]
). Обычно переменный размер имеет смысл, посколькуcombinations
может зависеть от значения времени выполнения, но в моем случае мне всегда нужны только последовательности длины 2. - person 0x5453   schedule 01.04.2019x: Iterable[Tuple[str, str]] = ((a, b) for (a, b) in itertools.combinations('abc', 2))
. - person Nathan Vērzemnieks   schedule 22.04.2019