Я пытаюсь правильно ввести аннотацию кода в моем текущем проекте. Это включает в себя генераторы, которые получают значения через .send()
. До итерации этим генераторам отправляется None
за возможность перехода к первому yield.
В моем понимании правильная аннотация типа для генератора, который выдает TYPE_A
, получает TYPE_B
и возвращает None
, будет
Generator[TYPE_A, TYPE_B, None]
Поскольку первое значение, отправляемое генератору, может быть None
, я подумал, что более подходящим будет следующее:
Generator[TYPE_A, Optional[TYPE_B], NONE]
В PyCharm это прекрасно работает в самом простом случае.
def f(g: Generator[str, Optional[int], None]):
g.send(None)
None
, отправленный на генератор, помечается PyCharm как противоречие типов только если я заменяю Optional[int]
на int
.
Пока все хорошо. Однако если я дополню эту идею обобщениями, то либо PyCharm запутается, либо я запутался. Рассмотрим следующий случай.
(Согласно
Table = Dict[int, T] # Table is generic
Messages = Table[bytes] # Same as Dict[int, bytes]
из этого раздела в PEP483 Мне кажется, что следующий код должен быть правильно аннотирован. На этот раз со всеми импортами для легкого копирования и вставки.)
from typing import TypeVar, Tuple, Generator, Optional
TYPE_A = TypeVar("TYPE_A")
TYPE_B = TypeVar("TYPE_B")
TUPLE_A = Tuple[TYPE_A, float]
GENERATOR_A = Generator[TUPLE_A, Optional[TYPE_B], None]
GENERATOR_B = Generator[TYPE_B, Optional[TUPLE_A], None]
def example_interactive(system_a: GENERATOR_A[int, str], system_b: GENERATOR_B[str, int]):
system_b.send(None)
system_a.send(None)
Идея состоит в том, что TUPLE_A
имеет один универсальный тип TYPE_A
, а GENERATOR_A
и GENERATOR_B
каждый имеет два (одну переменную непосредственного типа и одну опосредованную над TUPLE_A
).
К сожалению, PyCharm говорит мне, что это не работает так. Подскажите, пожалуйста, неправильно ли я что-то понял или аннотации типов просто неправильно интегрированы в PyCharm?