说你有这样的东西:
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键入提示以自动完成任一方法的输出。
但是,如果我想将Point
和Line
放在单独的文件中怎么办?有什么方法可以自动完成吗?
答案 0 :(得分:1)
问题在于Line
根本不是point.py
中类型的名称,而Point
不是line.py
中类型的名称。用引号将它没有帮助;只是在解析字符串时延迟。它仍然必须最终解析为一种类型,因此您只是将事物延迟到它们解析为NameError
的地步,这无济于事。
如果您在import line
中进行Point
并且在import point
中进行Line
,则point.Point
和line.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)