__Python/PyCharm的插槽类型注释

__Python/PyCharm的插槽类型注释,python,pycharm,Python,Pycharm,如何为通过定义的属性提供类型注释?例如,对于这一类: 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.

如何为通过
定义的属性提供类型注释?例如,对于这一类:

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也可以处理它(实际上这对我现在来说是最重要的)。

\uuuuu>只告诉
type()
对象为潜在属性腾出空间。列表中的名称本身不是属性。你所拥有的只是一堆描述符。没有值,因此没有类型

因此,您需要创建实际的属性,这些属性具有类型注释的所有常规选项

对于Python 3.6及更高版本,请使用:

或者对于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
        # ...
其中,docstring中列出了每个参数的所有类型。如果类的
\uuuu init\uuuu
方法也涉及所有属性,则不需要伪方法

请注意,您不能为这些设置类默认值,这意味着您不能使用
ref\u seq\u idx=None\type:int
(Python 3.6之前)或
ref\u seq\u idx:int=None
(Python 3.6及更高版本)<代码>\uuuu插槽\uuuu
名称将转换为类上的描述符对象,因此名称已设置

最后但并非最不重要的一点是,我将认真研究为您构建这些类型的方法。对该库的支持已取消,因此类型信息将自动拾取:

@attr.s(slots=True)
class DiffMatch:
    ref_seq_idx = attr.ib(init=False)  # type: int
    # ...
您将获得免费生成的
\uuu repr\uu
方法。
init=False
注释告诉
attrs
不要在
\uuuuu init\uuuuu
中包含该名称,此时实例在实例化时根本不会设置该属性。

现在我的解决方案:

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__]))

是的,我知道
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
做什么。对于类型注释,我的主要意思是只指定一个由PyCharm识别的docstring。但你的意思是我应该在课堂上加上这样的东西
ref\u seq\u idx=None#type:int
Edit我刚刚尝试过,但它抱怨这与
\uuu slots\uu
中的类变量冲突。编辑确定,在
\uuuuu init\uuuuu
中执行相同的操作。@Albert:是的,在没有变量类型注释的Python版本上,不能为插槽设置类默认值,因为这些默认值会与
\uuuuu slots\uuuuu
创建的同名描述符对象冲突。请注意,如果这些属性没有任何默认值,
方法将在
getattr(self,a)
上抛出一个
AttributeError
。您的空
参数列表和
repr()
输出立即发生冲突。你不能通过传入值来重新创建你的
DiffMatch()
实例,所以你的
repr()
不应该假装它可以;我在回答中添加了一个例子和进一步的动机。
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__]))