<p>所以看起来<code>slice.indices(n)</code>返回要给<code>range</code>的参数,以获得应该反映在长度序列<code>n</code>的切片中的项索引(<s>尽管没有文档化的编辑:</s><strong>正如@ShadowRanger指出的,它确实是<a href="https://docs.python.org/3/reference/datamodel.html#slice.indices" rel="nofollow">documented</a>)。因此,以下几行的计算值相同:</p>
<pre><code># get some list to work on
my_list = list(range(100))
# slice syntax
print(my_list[1:15:3])
# regular item access
print(my_list[slice(1,15,3)])
# reinvent list slicing
print([my_list[i] for i in range(*slice(1,15,3).indices(len(my_list)))])
</code></pre>
<p>如您所见,结果列表的长度与<code>range(*slice(1,15,3).indices(len(my_list)))</code>的长度相同,这取决于<code>slice</code>对象本身以及要切片的序列的长度。这就是为什么<code>len(range(*slice.indices(n)))</code>将在Python 3中给出正确的答案。(range对象是一个生成器,幸运的是它定义了<code>__len__</code>函数,因此它可以提供项目计数,而无需枚举和计数它们。)</p>
<p>如果在python 2中使用大数,可以按照@ShadowRanger的建议复制计算。</p>
<p><code>range.__len__</code>的原始实现如下:</p>
<pre><code>/* Return number of items in range (lo, hi, step). step != 0
* required. The result always fits in an unsigned long.
*/
static unsigned long
get_len_of_range(long lo, long hi, long step)
{
/* -------------------------------------------------------------
If step > 0 and lo >= hi, or step < 0 and lo <= hi, the range is empty.
Else for step > 0, if n values are in the range, the last one is
lo + (n-1)*step, which must be <= hi-1. Rearranging,
n <= (hi - lo - 1)/step + 1, so taking the floor of the RHS gives
the proper value. Since lo < hi in this case, hi-lo-1 >= 0, so
the RHS is non-negative and so truncation is the same as the
floor. Letting M be the largest positive long, the worst case
for the RHS numerator is hi=M, lo=-M-1, and then
hi-lo-1 = M-(-M-1)-1 = 2*M. Therefore unsigned long has enough
precision to compute the RHS exactly. The analysis for step < 0
is similar.
---------------------------------------------------------------*/
assert(step != 0);
if (step > 0 && lo < hi)
return 1UL + (hi - 1UL - lo) / step;
else if (step < 0 && lo > hi)
return 1UL + (lo - 1UL - hi) / (0UL - step);
else
return 0UL;
}
</code></pre>
<p>以及<code>slice.indices</code>:</p>
<pre><code>int
PySlice_GetIndices(PySliceObject *r, Py_ssize_t length,
Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
{
/* XXX support long ints */
if (r->step == Py_None) {
*step = 1;
} else {
if (!PyInt_Check(r->step) && !PyLong_Check(r->step)) return -1;
*step = PyInt_AsSsize_t(r->step);
}
if (r->start == Py_None) {
*start = *step < 0 ? length-1 : 0;
} else {
if (!PyInt_Check(r->start) && !PyLong_Check(r->step)) return -1;
*start = PyInt_AsSsize_t(r->start);
if (*start < 0) *start += length;
}
if (r->stop == Py_None) {
*stop = *step < 0 ? -1 : length;
} else {
if (!PyInt_Check(r->stop) && !PyLong_Check(r->step)) return -1;
*stop = PyInt_AsSsize_t(r->stop);
if (*stop < 0) *stop += length;
}
if (*stop > length) return -1;
if (*start >= length) return -1;
if (*step == 0) return -1;
return 0;
}
</code></pre>
<p>来源于<a href="https://svn.python.org/projects/python/trunk/Objects/" rel="nofollow">svn</a></p>