Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python - how slice([1,2,3]) works and what does slice(None, [1, 3], None) represent?

Documentation for class slice(start, stop[, step]):

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

What is going in the code and why the slice class init even allows a list as its argument?

print(slice([1,3]))
---
slice(None, [1, 3], None)

print(slice(list((1,3))))
---
slice(None, [1, 3], None)  # why stop is list?

hoge = [1,2,3,4]
_s = slice(list((1,3)))
print(hoge[_s])
--------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-59-1b2df30e9bdf> in <module>
      1 hoge = [1,2,3,4]
      2 _s = slice(list((1,3)))
----> 3 print(hoge[_s])

TypeError: slice indices must be integers or None or have an __index__ method

Updae

Thanks to the answer from Selcuk.

sliceobject.c#L303-L322

static PyObject *
slice_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
    PyObject *start, *stop, *step;

    start = stop = step = NULL;

    if (!_PyArg_NoKeywords("slice", kw))
        return NULL;

    if (!PyArg_UnpackTuple(args, "slice", 1, 3, &start, &stop, &step))
        return NULL;

    /* This swapping of stop and start is to maintain similarity with
       range(). */
    if (stop == NULL) {
        stop = start;       // <-----
        start = NULL;
    }
      
    return PySlice_New(start, stop, step);  // PySlice_New in L110 in the same file
}
like image 271
mon Avatar asked Dec 30 '22 18:12

mon


1 Answers

From the documentation:

Slice objects have read-only data attributes start, stop and step which merely return the argument values (or their default). They have no other explicit functionality [...]

So they are simply dummy objects that keep whatever you pass them. You can even pass strings or other objects:

my_slice = slice("foo", "bar", "baz")

[...] however they are used by Numerical Python and other third party extensions.

It is the third party extension's job to validate if the start, stop, and step values make any sense.

Also see the CPython implementation.

When you only pass one argument it is assumed to be the stop value. That's why you end up with start and step values set to None:

class slice(stop)

class slice(start, stop[, step])

like image 167
Selcuk Avatar answered Jan 02 '23 07:01

Selcuk