mypy:基类没有属性x,如何在基类中键入提示

时间:2018-07-05 12:14:24

标签: python annotations type-hinting mypy

我最近发现了mypy,并且希望对其进行类型检查。

我有一个Connector基类:

class Connector():
    ... some methods, but no __init__ ...

我有几个子类,它们都是连接器,但类型不同:

class Siphon(Connector)
    def __init__():
        short_name = "S"


class Tube(Connector)
    def __init__():
        short_name = "T"

使用这些对象时,通常将它们放在列表中:

c1 = Siphon()
c2 = Tube()
list_connectors: List[Connector] = list()
list_connectors.append(c1)
list_connectors.append(c2)

现在让我们说我想编写一个函数以列表形式返回所有连接器的所有短名称。我会写这样的东西:

def get_names(list_connectors: List[Connector]) -> List[str]:
    tmp_list: List[str] = list()
    for c in list_connectors:
        tmp_list.append(c.short_name)
    return tmp_list

当我这样做时,mypy抱怨:

error: "Connector" has no attribute "short_name"

这是正确的,基类连接器没有此属性,只有子类。但是所有连接器子类都将具有此属性。

我该如何纠正?我不能在这里使用class属性,因为我所有的子类都需要自己的short_name属性。

我应该在我的get_names函数的类型提示中使用Union(在我的实际情况下,有两种以上类型的连接器,并且我的API用户可以添加自己的连接器)?< / p>

我也不确定我可以编写一个基本的__init_函数并在子类中重写它,因为所有子类都有不同的init

2 个答案:

答案 0 :(得分:3)

如果您使用的是python 3.6或更高版本,则

class Connector():
    short_name: str
    ...

应该工作。该名称空间实际上并不存在,但是MYPY会找到它。参见https://www.python.org/dev/peps/pep-0526/


另一种选择是

import abc
class Connector(abc.ABC):
    @abc.abstractmethod
    @property
    def short_name(self) -> str:
        ...

答案 1 :(得分:3)

您需要将该属性添加到基本类型中;您不需要为其赋值:

class Connector:
    short_name: str

这使用Python 3.6的Variable Annotation syntax,它在Python 3.6或更高版本中是新的。它定义了 instance 属性的类型,而不是class属性(具有a separate syntax的class属性)。

否则,您可以使用注释,这时您必须给该属性一个初始值,并且是一个类属性:

class Connector:
   short_name = ''  # type: str