Единственный обходной путь, о котором я знаю, - это определить любые псевдонимы пользовательских типов так, чтобы они существовали только во время проверки типа, а не во время выполнения.
Для этого выпотребуется:
- Определить псевдонимы любого типа внутри
if typing.TYPE_CHECKING:
блоков.Блок typing.TYPE_CHECKING
всегда имеет значение false во время выполнения и считается проверяющим типом как true. - Убедитесь, что у вас либо все ваши подсказки типа, что и строки, или, если вы используете Python 3.7,добавить
from __future__ import annotations
, который делает это автоматически.То есть, во-первых, не нужно когда-либо оценивать подсказки типов.
Так, например, в вашей конкретной настройке вы можете добавить заглушки для библиотеки OrderedSet где-нибудь, а затем написать свой код, чтобы он выглядел следующим образом(предположим, Python 3.7 +):
from __future__ import annotations
from typing import TYPE_CHECKING
from ordered_set import OrderedSet
# Basically equivalent to `if False`
if TYPE_CHECKING:
IntOrderedSet = OrderedSet[Int]
def expects_int_ordered_set(x: IntOrderedSet) -> None:
# blah
some_ordered_set: IntOrderedSet = OrderedSet()
Или, если вы используете Python 3.6 или ниже:
from typing import TYPE_CHECKING
from ordered_set import OrderedSet
if TYPE_CHECKING:
IntOrderedSet = OrderedSet[Int]
def expects_int_ordered_set(x: 'IntOrderedSet') -> None:
# blah
some_ordered_set: 'IntOrderedSet' = OrderedSet()
Если вы в порядке немного врать, мы могли бы отказатьсясо строкой вещи и определите IntOrderedSet
, чтобы немного отличаться во время проверки типа от времени выполнения.Например:
from typing import TYPE_CHECKING
from ordered_set import OrderedSet
if TYPE_CHECKING:
IntOrderedSet = OrderedSet[Int]
else:
IntOrderedSet = OrderedSet
def expects_int_ordered_set(x: IntOrderedSet) -> None:
# blah
some_ordered_set = IntOrderedSet()
Будьте осторожны, когда вы делаете это, хотя - средство проверки типов не проверяет ничего в блоке 'else' / не проверяет, чтобы убедиться, что выто, что вы делаете, согласуется с тем, что находится в блоке if TYPE_CHECKING
.
Окончательное решение состоит в том, чтобы просто не определять тип IntOrderedSet
в первую очередь.Это позволяет нам пропустить хак 1, при этом нужно всего лишь использовать хак 2 (что не так уж много взлома - это будет поведение по умолчанию в Python через несколько лет).
Так, например, мы могли бы сделать это:
from __future__ import annotations
from ordered_set import OrderedSet
def expects_int_ordered_set(x: OrderedSet[int]) -> None:
# blah
some_ordered_set: OrderedSet[int] = OrderedSet()
В зависимости от контекста, может случиться, что мне даже не нужно добавлять аннотацию к этому последнему объявлению переменной.Здесь мы это делаем, но если бы мы определяли эту переменную внутри функции, вполне возможно, что средства проверки типов, такие как mypy, автоматически выведут для нас правильный тип в зависимости от того, как мы в итоге будем использовать эту переменную.