【发布时间】:2020-11-08 05:46:11
【问题描述】:
Python docs 有点模棱两可
顺序
一个支持通过
__getitem__()特殊方法使用整数索引的高效元素访问的可迭代对象,并定义了__len__()返回序列长度的方法。一些内置序列 类型是列表、字符串、元组和字节。注意 dict 也支持__getitem__()和__len__(),但被认为是映射而不是序列,因为查找使用任意不可变键而不是 整数。collections.abc.Sequence 抽象基类定义了一个更丰富的接口,不仅限于
__getitem__()和__len__(), 添加 count()、index()、__contains__()和__reversed__()。类型 实现这个扩展接口的可以显式注册 使用 register()。
特别是,使用abc.collections.Sequence 作为recommended by some 的黄金标准意味着,例如,numpy 数组不是序列:
isinstance(np.arange(6),collections.abc.Sequence)
# False
还有一个叫做 Sequence Protocol 的东西,但它似乎只在 C-API 中公开。那里的标准是
int PySequence_Check(PyObject *o)
如果对象提供序列协议,则返回 1,否则返回 0。请注意,它为带有 a 的 Python 类返回 1
__getitem__()方法,除非它们是 dict 子类,因为在一般情况下,无法确定它支持的键类型。 这个函数总是成功的。
最后,我不会太密切地关注这个新的(-ish)类型注释业务,但我想这也将受益于序列是什么的清晰概念。
所以我的问题既有哲学的一面,也有实用的一面:序列到底是什么?以及如何测试某事是否是序列?理想情况下,以某种方式制作 numpy 数组序列。如果我开始注释,我将如何处理序列?
【问题讨论】:
-
在
numpy代码中,我们看到诸如“使用序列设置数组元素”之类的错误。列表或元组会引发这种情况,但不会引发单个元素数组。arr[0] = [1]给出错误;arr[0]=np.array([1])没有。arr[0]=np.array([1,2])确实如此。 -
实际的答案是,类型匹配 Sequence 需要主动注册(通过继承或 Sequence.register)和方法定义,没有人费心去做。
-
@user2357112supportsMonica 我知道那篇文章并且实际上已经引用了它。不过,注释的角度是新的,在我看来,它似乎又增加了一个寻求清晰的理由。另外,
.index和.count没有在该线程中提及,所以我想知道它们是否是新的,collections.abc.Sequence已经将两种方法与核心/最小序列要求相距甚远。 -
并不是说它回答了问题的核心,但是,出于实际目的,如果您想使用专门针对序列和 NumPy 数组的类型注释,您也可以使用
Union:SequenceOrNdarray = Union[Sequence[Any], np.ndarray].