我有两个模块。模块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来说,这不是一个完整的类,因此它使用某种占位符类型。但这只是一种直觉。
我也愿意完全重构此示例,但我想尝试坚持这种常规结构。
答案 0 :(得分:1)
这是由于将模块视为脚本(无论是通过-m
,-c
(对于mypy还是--command
)而导致的许多破例之一,或简单地python …/module.py
)。它仅适用于不关心其创建的类型或功能的身份的琐碎应用程序。 (它们还必须避免对进口和易变的全球状态产生副作用,但无论如何都是好主意。)
除了“不要那样做”之外,解决方案是在软件包中使用__main__.py
。即使这样也不是没有问题,因为某些幼稚的递归进口商会像导入一个真正的模块一样将其导入。