python - Python / PyCharm 的 __slots__ 类型注释
问题描述
如何为通过定义的属性提供类型注释__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 可以处理它(实际上这对我来说现在最重要)。)
解决方案
__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
(pre-Python 3.6) 或ref_seq_idx: int = None
(Python 3.6 and up);__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__
此时实例在实例化时根本不会设置该属性。
推荐阅读
- angular - Angular - 在“then”块中访问ngrx存储
- python - python的socket中有没有像recv_until()这样的函数?
- algorithm - 如何区分元素在左子树或右子树中
- excel - 如果找不到文件,如何跳过代码块?
- python - 递归获取FTP文件夹及所有子文件夹的元数据
- c# - 如何从 lambda 对 AWS API Gateway 进行 REST 调用?
- r - 如何根据R中的给定序列对向量进行排序
- python - 在 KV 文件中更改 Kivy 类属性
- javascript - 为什么从 shelljs 执行工作的 shell 脚本会停止执行?
- c# - 停止标签在 Timer.Tick 上闪烁