mypy: base class has no attribute x, how to type hint in base class

泪湿孤枕 提交于 2019-12-12 10:58:01

问题


I recently discovered mypy and I want my code to be type checked with it.

I have a Connector base class:

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

And I have several subclasses, they are all connectors, but of different types:

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


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

When I use these objects, I normally put them in a list:

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

Now let's say I want to write a function to return all the short names of all the connectors, as a list. I'd write something like that:

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

When I do that, mypy complains:

error: "Connector" has no attribute "short_name"

Which is true, the base Class Connector doesn't have this attribute, only the subclasses. But all Connector subclasses will have this attribute.

How should I correct that? I can"t use a class attribute here since all my subclasses will need their own short_name attribute.

Should I use a Union in the type hinting of my get_names function (in my real life situation, there are much more than 2 types of connectors, and the user of my API could add his own)?

I'm also not sure I could write a base __init_ function and override it in the subclasses, because the subclasses all have a different init


回答1:


You'd add that attribute to the base type; you don't need to give it a value:

class Connector:
    short_name: str

This uses Python 3.6's Variable Annotation syntax, which is new in Python 3.6 or newer. It defines the type of an instance attribute, not a class attribute (for which there is a separate syntax).

You can use a comment otherwise, at which point you do have to give the attribute an initial value, and is a class attribute:

class Connector:
   short_name = ''  # type: str



回答2:


If you are using python 3.6 or later then

class Connector():
    short_name: str
    ...

should work. This doesn't actually exist in the namespace, but MYPY will find it. See https://www.python.org/dev/peps/pep-0526/.


Another option is to do

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


来源:https://stackoverflow.com/questions/51191061/mypy-base-class-has-no-attribute-x-how-to-type-hint-in-base-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!