如何为通过__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可以处理它(实际上这对我现在是最重要的。)
答案 0 :(得分:1)
__slots__
仅告诉type()
对象为潜在属性留出空间。列表中的名称不是本身就是属性。您所拥有的只是一堆描述符。没有值,所以没有类型。
因此,您需要创建实际属性,并且这些属性具有用于类型注释的所有常规选项。
对于Python 3.6及更高版本,请使用variable type annotations:
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
library为您构建这些类型。 recently been added to PyCharm 2018.2对此库提供了支持,因此会自动提取类型信息:
@attr.s(slots=True)
class DiffMatch:
ref_seq_idx = attr.ib(init=False) # type: int
# ...
,您将免费生成__repr__
方法。 init=False
注释指示attrs
不在__init__
中包括该名称,此时实例在实例化时根本不会设置该属性。
答案 1 :(得分:0)
我现在的解决方案:
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__]))