mypy: базовый класс не имеет атрибута x, как ввести подсказку в базовый класс - PullRequest
0 голосов
/ 05 июля 2018

Я недавно обнаружил 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"

Что верно, коннектор базового класса не имеет этого атрибута, только подклассы. Но все подклассы Connector будут иметь этот атрибут.

Как мне это исправить? Я не могу использовать атрибут класса здесь, так как все мои подклассы будут нуждаться в их собственном атрибуте short_name.

Должен ли я использовать Union в подсказке типа моей функции get_names (в моей реальной ситуации имеется более двух типов соединителей, и пользователь моего API может добавить свой собственный)?

Я также не уверен, что мог бы написать базовую __init_ функцию и переопределить ее в подклассах, потому что у всех подклассов есть различный init

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

Вы бы добавили этот атрибут к базовому типу; вам не нужно указывать это значение:

class Connector:
    short_name: str

При этом используется Python 3.6 Аннотация переменной синтаксис , который является новым в Python 3.6 или новее. Он определяет тип атрибута instance , а не атрибута класса (для которого существует отдельный синтаксис ).

В противном случае вы можете использовать комментарий, после чего вам необходимо присвоить атрибуту начальное значение, а это атрибут класса:

class Connector:
   short_name = ''  # type: str
0 голосов
/ 05 июля 2018

Если вы используете 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:
        ...
...