Python PyCharm中跨文件的循环类型批注为假阳性?

Python PyCharm中跨文件的循环类型批注为假阳性?,python,python-3.x,pycharm,circular-dependency,type-hinting,Python,Python 3.x,Pycharm,Circular Dependency,Type Hinting,我有一个中等规模的项目,在跨文件的对象之间有许多相互关系。我目前正在学习类型注释,我正在尝试完成我的项目,并尽可能地添加它们 有时,这些类型注释必须引用一个尚未初始化的类,因此我使用from\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu导入注释惰性地解析引用。当被引用的类出现在同一个文件中,但不在另一个文件中时,这确实满足了PyCharm的引用检查器的要求,因为它希望我执行循环导入以解析引用 我的测试包:茎和叶 我做了一个最小的测试包来尝试不同的解决方案。在

我有一个中等规模的项目,在跨文件的对象之间有许多相互关系。我目前正在学习类型注释,我正在尝试完成我的项目,并尽可能地添加它们

有时,这些类型注释必须引用一个尚未初始化的类,因此我使用
from\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu导入注释
惰性地解析引用。当被引用的类出现在同一个文件中,但不在另一个文件中时,这确实满足了PyCharm的引用检查器的要求,因为它希望我执行循环导入以解析引用

我的测试包:
我做了一个最小的测试包来尝试不同的解决方案。在这个测试包中,我试图实现一个简单的“茎叶”关系,其中一个
引用了许多
,每个
都引用了它的
。为此,我可以制作
Leaf
import
Stem
,或者
Stem
import
Leaf
。这两种方法在没有类型注释的情况下都满足PyCharm,并且它们也使用类型注释编译和运行,尽管PyCharm的引用检查器在这两种情况下都对我大喊大叫

方法1:
Leaf
importing
Stem
“测试\u循环\u注释/stem\u然后\u叶/stem.py”
从未来导入注释
干级:
定义初始化(自)->无:
self.leaves:列表[Leaf]=[]
def\uu getitem\uuu(self,index:int)->叶:
返回self.leaves[索引]
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
stem=stem()
“test\u circular\u annotations/stem\u then\u leaf/leaf.py”
从键入导入可选
从test_circular_annotations.stem_,然后从leaf.stem导入stem
类叶:
def uuu init(self,stem:可选[stem]=None)->None:
self.stem=stem
@财产
def阀杆(自)->可选[阀杆]:
返回自我_
@茎叶塞特
def阀杆(自身,值:可选[阀杆]->无:
self.\u stem\u=值
如果value和self不在value.leaves中:
value.leaves.append(self)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
stem=stem()
叶=叶(茎)
断言茎是叶。茎是茎[0]。茎
会发生什么?
stem.py
leaf.py
都成功执行,但PyCharm在
stem.py
中标记对
leaf
的引用,要求我从
leaf.py
导入
leaf
——这当然会导致运行时出现
ImportError

方法2:
导入
“测试循环注释/leaf\u然后测试stem/stem.py”
从test_circular_annotations.leaf_,然后从stem.leaf导入leaf
干级:
定义初始化(自)->无:
self.leaves:列表[Leaf]=[]
def\uu getitem\uuu(self,index:int)->叶:
返回self.leaves[索引]
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
stem=stem()
叶=叶(茎)
断言茎是叶。茎是茎[0]。茎
“测试循环注释/leaf\u然后测试stem/leaf.py”
从未来导入注释
从键入导入可选
类叶:
def uuu init(self,stem:可选[stem]=None)->None:
self.stem=stem
@财产
def阀杆(自)->可选[阀杆]:
返回自我_
@茎叶塞特
def阀杆(自身,值:可选[阀杆]->无:
self.\u stem\u=值
如果value和self不在value.leaves中:
value.leaves.append(self)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
叶=叶()
会发生什么? 同样,
stem.py
leaf.py
都成功执行,但这次PyCharm在
leaf.py
中标记对
stem
的引用

TL;博士 以下是PyCharm中项目的外观:

左侧为叶片导入茎;右边是茎叶。同样,所有模块都正常运行,但每种情况都会预先触发PyCharm的参考检查程序

我觉得这只是PyCharm中的一个bug,但为了以防万一,我先在这里发布这个,因为它似乎是一个常见的问题,可能只是一个规范Python解决方案的“我的问题”。我真的不想把所有相关对象的集合都放在同一个文件中——考虑到在这两者之间的选择和省略类型注释,我肯定会选择后者


我该怎么办?提前感谢:)

假设您正在定义一个类“a”,并且有一个方法“m”接收“a”的实例。由于“m”在“A”中,而类“A”尚未定义,因此您无法编写
defm(self,other_A:A)->None:
。正确的方法是编写
defm(self,other_a:“a”)->None:
(也就是说,使用类型名而不是实际类型的字符串)。也许在你的案例中也可以使用相同的方法,但我没有尝试过。是的,根据我的理解,这曾经是正确的,但是通过从未来导入注释可以让你只写
defm(self,other_a:a)->None:
。问题不在于Python本身,它再次编译并运行代码,而在于PyCharm,因为它知道我试图引用一些不存在的东西,但它不知道Python在这个实例中不在乎。用一个引用字符串替换引用并不会改变IDE中的这一点。值得尝试“a”解决方案来查看它是否接受它。它可能不支持
from\uuuuu future\uuuuu import annotations
选项,但仍然可以使用string选项。它不起作用。假设您正在定义一个类“a”,并且有一个方法“m”接收“a”的实例。由于“m”在“A”中,而类“A”尚未定义,因此您无法编写
defm(self,other_A:A)->None:
。正确的方法是编写
defm(self,other_a:“a”)->None:
(即使用一个名为