跨文件输入具有循环依赖性的提示

时间:2018-08-23 15:55:03

标签: python python-3.x pycharm

说你有这样的东西:

class Point:
    def compute_line(self, point: 'Point') -> 'Line':
        # computes line connecting self to point
        ...


class Line:
    def compute_intersection(self, line: 'Line') -> 'Point':
        # computes point formed from intersection of self and line
        ...

PyCharm可以解析str键入提示以自动完成任一方法的输出。

但是,如果我想将PointLine放在单独的文件中怎么办?有什么方法可以自动完成吗?

2 个答案:

答案 0 :(得分:1)

问题在于Line根本不是point.py中类型的名称,而Point不是line.py中类型的名称。用引号将它没有帮助;只是在解析字符串时延迟。它仍然必须最终解析为一种类型,因此您只是将事物延迟到它们解析为NameError的地步,这无济于事。

如果您在import line中进行Point并且在import point中进行Line,则point.Pointline.Line成为类型,这可以解决该问题。但是,这当然会带来一个新问题:循环导入。


在某些情况下,as explained in PEP 484,您可以通过执行条件“仅静态键入”导入来解决此问题,如下所示:

import typing
if typing.TYPE_CHECKING:
    import line

…,然后在类型注释中使用'line.Line'

有关更多详细信息,请参见TYPE_CHECKING上的文档。 (特别是,如果您需要与3.5.2之前的Python 3.5兼容,这将在运行时为您提供NameError而不是False,这很痛苦……但是并没有很多人需要在3.5上运行.1。)


如果这不能解决问题,则需要某种方案来避免循环导入,就像运行时循环导入一样。

例如,您可以使用传统的“接口”解决方案,其中第一种类型依赖于第二种,但是第二种不依赖于第一种,它仅依赖于超类。

通常,该超类将是ABC,表示它仅充当与其他地方定义的某些真实类的接口。 (通过这种方式,Python和您的静态检查器可以强制执行,任何键入为ABC的东西都必须是该ABC的具体子类之一的实例,而该子类只有一个。)

# pointbase.py
import abc
class PointBase(abc.ABC):
    @abc.abstractmethod
    def method_that_does_not_need_line(self):
        pass

# point.py
import pointbase
import line
class Point(pointbase.PointBase):
    def method_that_does_not_need_line(self):
        do_stuff()
    def method_that_does_need_line(self, line: line.Line):
        do_stuff(line)

# line.py
import pointbase
class Line:
    def method_that_needs_point(self, point: pointbase.PointBase):
        do_stuff(point)

答案 1 :(得分:0)

您可以对此类型声明,PyCharm会将其识别为您所声明的类型。

assert isinstance(point, Point)