为什么顺序在类型提示中很重要?

Why does ordering matter in type hinting?

为什么这样可以

class Ship:

    def __init__(self, parent):
        self.parent = parent

class Fleet:

    def __init__(self):
        self.ships = []

    def add_ship(self, ship: Ship):
        self.ships.append(ship)

但这不是吗?

class Fleet:

    def __init__(self):
        self.ships = []

    def add_ship(self, ship: Ship):
        self.ships.append(ship)

class Ship:

    def __init__(self, parent):
        self.parent = parent

我知道导入时不能有循环引用。但是,这不是重要的事情:这两个都在同一个文件中。在这两种情况下,都定义了 Ship,但似乎如果先定义了 Fleet,它就找不到 Ship 的定义。如果我使用 isinstance 检查类型,这 不是 true。

def add_ship(self, ship):
    if isinstance(ship, Ship): # works fine
        self.ships.append(ship)

但是,这不允许我的 IDE (PyCharm) 查看定义和自动完成语法。

事实上,下面的设计模式似乎工作得很好

class Fleet:

    def __init__(self):
        self.ships = []

    def add_ship(self, ship):
        if isinstance(ship, Ship):
            self.ships.append(ship)

class Ship:

    def __init__(self, parent):
        if isinstance(parent, Fleet):
            self.parent = parent

但是,同样,我的 IDE 无法确定类型。这是Python3.6.5/Anaconda/Windows10.

def add_ship(self, ship: Ship): 定义时间 计算。那个时候Ship还没有定义

if isinstance(ship, Ship): 仅在调用 add_ship 时计算。这将(希望)仅在定义 Ship 之后。

PEP 563(在 Python 3.7 及更高版本中实现)通过使类型注释评估惰性来解决此问题。

如果升级,您可以将 from __future__ import annotations 添加到文件的顶部,该示例将起作用。

这将在 Python 4.0 中完全实现,这意味着将不需要 from __future__ import annotations

前Python3.7解决方案

如果您不能或不想升级到 Python >= 3.7,您可以使用字符串文字注释(我链接到的 PEP 中也提到了):

def add_ship(self, ship: 'Ship'):