#python #generics #mypy
Вопрос:
Я боролся со странными ситуациями, когда mypy счастлив, но python выходит из строя, когда я запускаю код. Вот проблема, с которой я сталкиваюсь с дженериками. У меня есть два файла в одном каталоге. Когда я запускаю python3 sample_parser.py
, я получаю следующую ошибку:
Traceback (most recent call last):
File "/Users/joe/repos/ut-norm-james/so_generics/sample_parser.py", line 8, in <module>
class SampleParser(LookaheadParser[str]):
NameError: name 'LookaheadParser' is not defined
Вот lookahead_parser.py
:
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from typing import TypeVar, Generic, Optional, Callable
_T = TypeVar("_T")
StateFunc = Callable[[_T], Callable]
class LookaheadParser(Generic[_T]):
def __init__(self):
self._token_index: int = 0
self._tokens: list[_T] = []
self._state: StateFunc
def _parse(self) -> None:
while self._token_index < len(self._tokens):
self._state = self._state(self._tokens[self._token_index])
self._token_index = 1
def _lookahead(self, offset: int) -> Optional[_T]:
prospective_index = self._token_index offset
if prospective_index < len(self._tokens):
return self._tokens[prospective_index]
return None
def _advance(self, offset: int) -> None:
self._token_index = offset
Вот sample_parser.py
:
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from .lookahead_parser import LookaheadParser, StateFunc
class SampleParser(LookaheadParser[str]):
def __init__(self, raw_text: str):
self._raw_text = raw_text
self._state = self._state_first
def parse(self) -> None:
self._parse()
def _state_first(self, token: str) -> StateFunc:
pass # stub
if __name__ == "__main__":
pass # stub
Я запускаю Python 3.9.6, но это также происходило в 3.9.5. Проблема возникает независимо от того , использую ли я _T
или T
, если вы косо на это смотрите. сама mypy не сообщает о каких-либо проблемах.
Ответ №1:
Вы импортируете только lookahead_parser
в том случае, если TYPE_CHECKING
это правда. Эта переменная имеет значение false во время выполнения, поэтому модуль никогда не загружается. Просто удалите if TYPE_CHECKING:
деталь и выполните импорт безоговорочно.
from .lookahead_parser import LookaheadParser, StateFunc
Комментарии:
1. Икса! Спасибо! Я должен был это предвидеть. Но теперь я получаю
TypeVar
не определено, когда я запускаю python. Похоже, что flake8 и mypy недостаточно, чтобы сказать мне, есть ли в коде необходимые определения. Я запускаю VSCode, потому что PyCharm плохо справлялся с подсказками типа.2. Удаление всего импорта из TYPE_CHECKING решило эту проблему. Я просто хотел бы, чтобы мне рассказали об этих проблемах до выполнения. Спасибо за вашу помощь!
3. Просто пока избегайте переменной
TYPE_CHECKING
. Это позволяет вам выполнять сложные трюки с метапрограммированием и обходить проверку типов, и я сомневаюсь, что вам все равно понадобится что-то из этого.4. Я нахожу, что все мои другие проблемы с использованием типов решаются путем извлечения импорта из проверки типов. Я начал использовать проверку ТИПОВ, чтобы обойти очевидные циклические зависимости, используя типы в PyCharm. Похоже, мне следовало прекратить использовать проверку типов, когда я переключился на VSCode и mypy, так как подсказки типа теперь, похоже, ведут себя так, как описано в документах. Еще раз спасибо!
5. Мне действительно пришлось добавить
if TYPE_CHECKING
несколько модулей, но, по крайней мере, теперь это имеет смысл-каждый из этих модулей включал в себя другой.