【问题标题】:Which built-in abstract base classes support slicing?哪些内置抽象基类支持切片?
【发布时间】:2020-05-28 09:39:05
【问题描述】:

Python 的文档在https://docs.python.org/3/library/collections.abc.html 处非常清楚地列出了抽象基类的实现应该具有的所有方法。 然而,切片有时仅作为__getitem__ 的一部分实现。

我想所有继承自Sequence 的类都会实现它,是这样吗?还有其他方法可以知道对象支持切片吗?

编辑:我还在文档中找到了https://docs.python.org/3/library/stdtypes.html#typesseq-common。它将方法列为“大多数序列类型支持”。
我将其视为“序列类型应实现切片”并使用它进行注释。

【问题讨论】:

  • “pythonic”的方式是尝试做它并查看是否引发异常。
  • 曾经有一个__getslice__ 方法,但在很久之前通过将slice 对象传递给__getitem__ 来取代它。实际上并没有一类专门实现切片的类型,就像没有可以用int 值索引的类型与可以用str 值索引的类型一样。
  • 似乎隐含 Sequence 是一种其顺序由其索引排序确定的类型,而 Mapping 是一种其顺序(如果定义在全部)不是。

标签: python slice abstract-base-class


【解决方案1】:

typeshed/typing.pyi 中,Sequence 的类型如下:

class Sequence(_Collection[_T_co], Reversible[_T_co], Generic[_T_co]):
    @overload
    @abstractmethod
    def __getitem__(self, i: int) -> _T_co: ...
    @overload
    @abstractmethod
    def __getitem__(self, s: slice) -> Sequence[_T_co]: ...
    ...

https://github.com/python/typeshed/blob/master/stdlib/3/typing.pyi#L274

因此,任何序列类型都应该支持切片。在类型模块中没有为其他类型指示切片。例如,映射显式列出了映射的键类型。

【讨论】:

  • 小心根据类型提示做出假设。例如,Mapping 在其键类型和值类型上都是完全通用的,但dict 不允许使用不可散列的键。这表示Sequence 可以 支持slice 对象作为参数,但除了返回类型是具有相同元素类型的另一个序列之外,没有关于应该如何使用slice。 (例如,类型提示允许每个切片操作返回一个空元组,无论具体的序列类型如何。)
  • 有趣的是,dict 的键类型也是完全通用的。看来 Hashable 是一个他们还没有弄清楚的特例。
  • 鉴于官方(打字)实现表明在序列上支持切片,我将使用它。在 Python 中,您可能在没有实现抽象方法的情况下(正确地)将某些东西指示为子类,但我们可以对任何子类这么说。我宁愿将这些情况视为错误,也不愿使用类型提示。
  • 我同意实现切片的类应该Sequence的子类;我只是不同意作为Sequence 的子类保证支持切片。
【解决方案2】:

TL;DR 没有这样的子类,因为 Python 只定义了切片的语法,没有定义任何语义。


为了成为SequenceMapping 的子类,类必须实现__getitem__。但是,ABC 都没有要求对__getitem__ 进行任何特定的实现;如何解释 index 参数完全取决于实现类。

切片并不是真正的特殊操作;它只是指定slice 类型参数的特殊语法。以下是等价的:

foo[1:3,2::9]
foo[slice(1,3), slice(2,None,9)]

__getitem__签名而言,传递一个int、一个str、一个slice对象或一个包含任何类型的组合。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-10-23
    • 2012-01-28
    • 2021-01-09
    • 2010-11-27
    • 1970-01-01
    • 2016-09-20
    • 2018-12-14
    • 2011-06-10
    相关资源
    最近更新 更多