Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 943
JPFrancoia Avatar asked Jul 05 '18 12:07

JPFrancoia


People also ask

How do I make MYPY ignore error?

Silencing errors based on error codes You can use a special comment # type: ignore[code, ...] to only ignore errors with a specific error code (or codes) on a particular line. This can be used even if you have not configured mypy to show error codes.

How do I use type ignore?

You can use the form # type: ignore[<code>] to only ignore specific errors on the line. This way you are less likely to silence unexpected errors that are not safe to ignore, and this will also document what the purpose of the comment is.


1 Answers

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
like image 165
Martijn Pieters Avatar answered Sep 30 '22 18:09

Martijn Pieters