аннотации типа __slots__ для Python / PyCharm - PullRequest
0 голосов
/ 28 сентября 2018

Как я могу предоставить аннотации типов для атрибутов, которые определены с помощью __slots__?Например, для этого класса:

class DiffMatch:
  __slots__ = ["ref_seq_idx", "ref_txt", "hyp_txt", "start_time", "end_time"]

  def __repr__(self):
    return "%s(%s)" % (self.__class__.__name__, ", ".join(["%s=%r" % (a, getattr(self, a)) for a in self.__slots__]))

(Python 2 совместим в комментариях, если это возможно (в противном случае Python 3 подходит только), а также так, что PyCharm может справиться с этим (на самом деле это сейчас для меня наиболее важно).)

Ответы [ 2 ]

0 голосов
/ 28 сентября 2018

Мое решение сейчас:

class DiffMatch:
  __slots__ = ["ref_seq_idx", "ref_txt", "hyp_txt", "start_time", "end_time"]

  def __init__(self):
    self.ref_seq_idx = None  # type: int
    self.ref_txt = None  # type: str
    self.hyp_txt = None  # type: str
    self.start_time = None  # type: Decimal
    self.end_time = None  # type: Decimal

  def __repr__(self):
    return "%s(%s)" % (self.__class__.__name__, ", ".join(["%s=%r" % (a, getattr(self, a)) for a in self.__slots__]))
0 голосов
/ 28 сентября 2018

__slots__ только говорит объекту type(), чтобы освободить место для потенциальных атрибутов.Имена в списке сами по себе не являются атрибутами .Все, что у вас есть, это куча дескрипторов.Нет значений, поэтому нет типов.

Поэтому вам нужно создать фактические атрибуты, и у них есть все обычные опции для аннотаций типов.

Для Python 3.6 и выше используйте аннотации типов переменных :

class DiffMatch:
    __slots__ = ["ref_seq_idx", "ref_txt", "hyp_txt", "start_time", "end_time"]

    ref_seq_idx: int
    # ...

или для версий до 3.6 (включая Python 2) необходимо аннотировать типы в методе, который может устанавливать атрибуты.В противном случае нет реальной поддержки атрибутов экземпляра.Для этого можно добавить фиктивный метод:

class DiffMatch:
    __slots__ = ["ref_seq_idx", "ref_txt", "hyp_txt", "start_time", "end_time"]

    def __type_hints__(self, ref_seq_idx, ...):
        """Dummy method to annotate the instance attribute types
        # type: (int, ...) -> None
        """
        self.ref_seq_idx = ref_seq_idx
        # ...

, где все типы для каждого из аргументов перечислены в строке документации.Если у вас есть метод __init__ для вашего класса, который также касается всех атрибутов, тогда фиктивный метод не нужен.

Обратите внимание, что вы не можете установить значения класса по умолчанию для них, что означает, что вы можетене использовать ref_seq_idx = None # type: int (до Python 3.6) или ref_seq_idx: int = None (Python 3.6 и выше);__slots__ имена преобразуются в объекты-дескрипторы класса, поэтому имена уже установлены.

И последнее, но не менее важное: я бы серьезно посмотрел на библиотеку attrs , чтобыпостроить эти типы для вас.Поддержка этой библиотеки была недавно добавлена ​​в PyCharm 2018.2 , поэтому информация о типе автоматически выбирается:

@attr.s(slots=True)
class DiffMatch:
    ref_seq_idx = attr.ib(init=False)  # type: int
    # ...

, и вы получите метод __repr__, созданный бесплатно.Аннотация init=False указывает attrs не включать это имя в __init__, и в этом случае экземплярам вообще не будет задан этот атрибут при создании экземпляра.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...