slice(start, stop, None) 和 slice(start, stop, 1) 的区别是什么?

9

我很惊讶地在这里阅读到:

startstep 参数默认为 None

因为它还说:

slice(start, stop, step=1)

Return a slice object representing the set of indices specified by range(start, stop, step).

所以我预期step参数的默认值为1

我知道slice(a, b, None) == slice(a, b, 1)返回False,但我很好奇slice(a, b, None)是否总是返回与slice(a, b, 1)相同的切片,或者是否有一些我无法想到的例子,它们会返回不同的切片。

在关于切片的详细帖子这里中,我找不到任何相关信息。


3
这很可能是默认参数和默认行为之间的区别。当step为None时,它被处理为1,但仍存储为None(与1不同)。 - Alain T.
1
嗯,我觉得你发现了一个小的文档错误。slice的正确用法是slice(start, stop[, step]) - wim
1
有人可能会实现一个函数或类,以不同的方式解释步骤,因此需要知道切片是如何编写的,例如 1:5 还是 1:5:1 - Michael Butscher
1
我已经为文档错误添加了 https://github.com/python/cpython/pull/107756。 - wim
1
@Joe 我同意范围比较并不是很有帮助/准确。就个人而言,我只是把slice(x, y, z)看作是从语法obj[x:y:z]中在__getitem__中接收到的实例,并且不试图与范围进行类比。 - wim
显示剩余2条评论
1个回答

7
Slice的步长确实默认为None, 但是对于所有实际目的来说,使用步长1None应该是等效的。这是因为在实际使用步长的C代码中,有检查将None转换为1
int
PySlice_GetIndices(PyObject *_r, Py_ssize_t length,
                   Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
{
    PySliceObject *r = (PySliceObject*)_r;
    if (r->step == Py_None) {
        *step = 1;
    } ...    
}

而且:

int
PySlice_Unpack(PyObject *_r,
               Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
{
    PySliceObject *r = (PySliceObject*)_r;
    ...
    if (r->step == Py_None) {
        *step = 1;
    }
    ...
}

如果你想知道为什么他们不直接默认为1,也许是因为用户可能仍然希望明确地使用None进行切片(例如L[1:2:None]),和/或者给第三方类型处理1None在它们的__getitem__/__setitem__/__delitem__实现中有所不同的机会。

从实际角度来看,它在哪些不切实际的情况下不会默认为1呢? - OverLordGoldDragon
2
@OverLordGoldDragon 比较切片实例是否相等。 - wim
PySlice_GetIndices这个函数实际上在哪里被使用?我猜是在内部的数据结构,比如list等等?因为如果你创建了s = slice(1, 10)然后打印s.stop,它会打印出None,所以如果你正在编写自己的数据结构并想要支持切片操作,你必须显式地处理None - juanpa.arrivillaga
1
@juanpa.arrivillaga 它由切片实例的 indices 方法使用。我想你指的是 s.step 而不是 s.stop ... 但是,是的,如果你正在编写自己的数据结构,你并不需要将 step=Nonestep=1 视为等价的。实际上,你甚至不需要使用整数(我曾经实现过一个类,它使用字符串作为切片来实现某种功能..) - wim
slice.indices 看起来也是 stable ABI 的一部分,自 3.2 版本开始。 - wim
1
啊,我之前不知道这个方法。那么,对于给定的长度,slice_object1.indices(some_length) == slice_object2.indices(some_length) 就能得到所需的语义。 - juanpa.arrivillaga

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接