问题
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