我有一个变量a=range(0,5)
,我需要知道为什么和如何 a[::-1]
这有效。我得到的答案是range(4,-1,-1)
。感谢帮助。
P.S。 这是一个非常基本的问题,但是由于该问题以非常结构化的方式回答,因此我尝试编辑该问题并使之更加通用和有用。
切片
start
和stop
的负数表示“从头开始”。基本上等于len-value
。step
的负数表示“反序”。len
。 Stop参数是独占的!因此,[::-1]
表示从第一个元素到最后一个元素,以相反的顺序以1为步长。
[start:stop]
,则与step=1
相同。因此,[:-1]
表示除最后以外的所有内容。再次是最后一个元素exclusive。与[:-1:]
或[0:-1:1]
相同。如果只有start
,它将返回由索引start
给出的一个元素。因此,[-1]
表示最后一个元素。与[len-1]
相同。
范围
范围也具有语法start,stop,step
,但步骤具有不同的含义。从start
开始重复添加步骤。因此,您从4
开始,然后向下添加-1
,直到您同样独占stop
。因此range(5,0)[::-1]
等于range(4,-1,-1)
。您可以计算出来。
为什么口译员说range(0,5)[::-1] => range(4, -1, -1)
?
Python解释器非常聪明,可以将range
的一部分转换为另一个range
。这是一个优化,范围是生成器。它们是动态的,即它们不会一次将所有元素保存在内存中。如果您正在使用的解释程序是逐步进行的,则它必须生成整个列表,只是为了能够以相反的顺序进行迭代。计算新发电机更智能。
如何完成,isukasz的答案有详细解释。
顺便说一句。您可以强制其生成list
,并阻止其优化:
range(0,5)[::-1]
=> range(4, -1, -1)
list(range(0,5))[::-1]
=> [4, 3, 2, 1, 0]
compute_slice
函数用于在现有compute_slice
对象(range
)和它的新值之间转换。如您所见,它基于rangeobject *r
和传递的range
的开始/停止/步长值作为O(1)操作完成。
slice
您使用的方法在Python中称为static PyObject *
compute_slice(rangeobject *r, PyObject *_slice)
{
PySliceObject *slice = (PySliceObject *) _slice;
rangeobject *result;
PyObject *start = NULL, *stop = NULL, *step = NULL;
PyObject *substart = NULL, *substop = NULL, *substep = NULL;
int error;
error = _PySlice_GetLongIndices(slice, r->length, &start, &stop, &step);
if (error == -1)
return NULL;
substep = PyNumber_Multiply(r->step, step);
if (substep == NULL) goto fail;
Py_CLEAR(step);
substart = compute_item(r, start);
if (substart == NULL) goto fail;
Py_CLEAR(start);
substop = compute_item(r, stop);
if (substop == NULL) goto fail;
Py_CLEAR(stop);
result = make_range_object(Py_TYPE(r), substart, substop, substep);
if (result != NULL) {
return (PyObject *) result;
}
fail:
Py_XDECREF(start);
Py_XDECREF(stop);
Py_XDECREF(step);
Py_XDECREF(substart);
Py_XDECREF(substop);
Py_XDECREF(substep);
return NULL;
}
。
切片语法如下,
Slicing
添加[ <first element to include> : <first element to exclude> : <step> ]
部分是可选的。
这里是python列表如何考虑正负索引的表示。
step
使用时,
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5
-6 -5 -4 -3 -2 -1
为什么,当我们将a = range(10)
# a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
a[10:0:-1] #or
a[-1:-10:-1]
# Output = [9, 8, 7, 6, 5, 4, 3, 2, 1]
/ 0
作为第二个参数时,它排除了位于第-10
/ 0
位的元素。
简便的方法是在切片时省略第二个参数。也就是说,
-10
为了进一步简化,如果您同时省略了起始值和结束值,而只将步长设为-1,则它再次产生相同的结果。
a[10::-1] #or
a[-1::-1]
# Output = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
# Which is what we want.
这里是用于理解切片的简单备忘单,
a[::-1]
# Output = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
# The -1 at step position traverse the element from the last to the beginning
要了解有关切片的更多信息,a[start:end] # items start through end-1
a[start:] # items start through the rest of the array
a[:end] # items from the beginning through end-1
a[:] # a copy of the whole array
a[start:end:step] # start through not past end, by step
a[-1] # last item in the array
a[-2:] # last two items in the array
a[:-2] # everything except the last two items
希望这会有所帮助! :)