slice(start, stop, None) vs slice(start, stop, 1)
Question:
I was surprised to read here that
The start
and step
arguments default to None
since it also says:
slice(start, stop, step=1)
Return a slice object representing the set of indices specified by range(start, stop, step).
So I expected the default argument value for the step
parameter to be 1
.
I know that slice(a, b, None) == slice(a, b, 1)
returns False
, but I am curious if slice(a, b, None)
always returns the same slice as slice(a, b, 1)
, or if there is some example that I haven’t been able to think of for which they will return different slices.
I couldn’t find anything about this in the extensive post on slicing here
Answers:
Slice’s step indeed defaults to None
, but using step 1
and None
should be equivalent for all practical purposes. That’s because in the C code where the step is actually used, there are checks which transform None
into 1
anyway:
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;
} ...
}
And:
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;
}
...
}
If you’re wondering why they don’t just default to 1
instead, perhaps it’s because users may still want to slice using None
explicitly (e.g. L[1:2:None]
), and/or to give 3rd-party types the opportunity to handle 1
and None
differently in their __getitem__
/__setitem__
/__delitem__
implementation.
I was surprised to read here that
The
start
andstep
arguments default toNone
since it also says:
slice(start, stop, step=1)
Return a slice object representing the set of indices specified by range(start, stop, step).
So I expected the default argument value for the step
parameter to be 1
.
I know that slice(a, b, None) == slice(a, b, 1)
returns False
, but I am curious if slice(a, b, None)
always returns the same slice as slice(a, b, 1)
, or if there is some example that I haven’t been able to think of for which they will return different slices.
I couldn’t find anything about this in the extensive post on slicing here
Slice’s step indeed defaults to None
, but using step 1
and None
should be equivalent for all practical purposes. That’s because in the C code where the step is actually used, there are checks which transform None
into 1
anyway:
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;
} ...
}
And:
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;
}
...
}
If you’re wondering why they don’t just default to 1
instead, perhaps it’s because users may still want to slice using None
explicitly (e.g. L[1:2:None]
), and/or to give 3rd-party types the opportunity to handle 1
and None
differently in their __getitem__
/__setitem__
/__delitem__
implementation.