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

时间:2019-01-09 16:09:53

标签: python-3.x 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检查类型,这是 not 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找出类型。这是Python 3.6.5 / Anaconda / Windows 10。

1 个答案:

答案 0 :(得分:7)

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

Python 3.7之前的解决方案

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

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