Фон
У меня есть два модуля. Модуль 1 (example
) определяет TestClass
. Модуль 2 (example2
) определяет функции change_var
, которые принимают аргумент TestClass
. example
имеет метод change
, который вызывает change_var
из example2
и передает self
в качестве аргумента.
example2
использует TYPE_CHECKING
из typing
, чтобы циклический импорт не появлялся во время выполнения, но все же позволяет MYPY проверять типы.
При звонке на change_var
из change
MYPY выдает ошибку Argument 1 to "change_var" has incompatible type "__main__.TestClass"; expected "example.TestClass"
.
Python версия: 3.7.3
,
MYPY версия: 0.701
Пример кода
example.py
from example2 import change_var
class TestClass:
def __init__(self) -> None:
self.test_var = 1
def change(self) -> None:
change_var(self)
example2.py
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from example import TestClass
def change_var(obj: "TestClass") -> None:
obj.test_var = 2
Этот код является минимальным примером реальной проблемы, с которой я сталкиваюсь в более крупном проекте Python.
Что я ожидаю от этого
Эти типы должны совпадать, поскольку они (насколько я могу судить) одинаковы.
Моя интуиция относительно того, почему это не работает, заключается в том, что TestClass
в точке вызова change_var
не полностью определено? По той же причине, по которой я не могу ссылаться на TestClass
как на тип внутри TestClass
, я не могу передать объект TestClass
в функцию, которая ожидает, что объект TestClass
не сможет покинуть сам класс. Для MYPY это еще не полный класс, поэтому он использует какой-то тип заполнителя. Это только интуиция.
Вопросы
- В чем точно здесь проблема?
- Как лучше всего обойти эту общую структуру кода (два модуля, класс в одном, функция, которая переводит класс в другой, вызовы методов для функции), в то же время делая MYPY счастливым?
Я также полностью готов к рефакторингу этого примера, но я хотел бы попытаться придерживаться этой общей структуры.