标题说明了自己,如何从对象中取出2
slice(0,2)
Run Code Online (Sandbox Code Playgroud)
该文档有些混乱,或者是错误的文档
https://docs.python.org/2/c-api/slice.html
特别是我不明白输出的含义是什么
slice(0,2).indices(0) # (0, 0, 1)
slice(0,2).indices(10 ** 10) # (0, 2, 1)
Run Code Online (Sandbox Code Playgroud)
一种可能的解决方法是使用slice对象对列表进行切片
a = [1,2,3,4,5]
len(a[slice(0,2)]) # 2
Run Code Online (Sandbox Code Playgroud)
但这对于任意大的切片都会失败。
谢谢,我在其他帖子中找不到答案。
没有完整的答案。slice
不会给出长度,因为结果的长度始终取决于要切片的序列的大小,较短的序列(包括空序列)将产生较少的项,并且如果slice
无限,则长度将增加与序列的长度一致;slice
通过使用start
或stop
,a 可能只是“到达序列末尾” None
。
为了快速简便地计算已知长度序列的长度,您可以将其.indices
与Py3组合range
(或xrange
在Py2中组合,尽管xrange
对Py3 range
没有限制)。slice.indices
为您提供具体的值start
,stop
以及stride
当将a slice
应用于给定长度的序列时派生的值,基本上是您要在C样式for
循环中填写的值,它们遍历与相同的索引slice
:
for (ssize_t i = start; i < stop; i += stride)
Run Code Online (Sandbox Code Playgroud)
因此,要计算slice
应用于1000个元素的序列时的长度,您需要执行以下操作:
>>> len(range(*slice(0, 2).indices(1000)))
2
>>> len(range(*slice(10, None, 3).indices(1000)))
330
Run Code Online (Sandbox Code Playgroud)
如果您使用的是Python 2,并且您的值可能超出了xrange
可以处理的范围(它的界限和总长度等于一个ssize_t
可以容纳的范围),则可以手动进行计算:
def slice_len_for(slc, seqlen):
start, stop, step = slc.indices(seqlen)
return max(0, (stop - start + (step - (1 if step > 0 else -1))) // step)
>>> slice_len_for(slice(10, None, 3), 1000)
330
Run Code Online (Sandbox Code Playgroud)
更新:不幸的是,slice.indices
它本身不会接受len
超出a long
可以容纳的范围的序列,因此这不会为您xrange
在Py2中使用带来任何好处。留给感兴趣的人使用,但是解决方法不会解决任何问题,除非您还执行该工作slice
以None
根据序列长度将负值转换为具体值。叹。
因此,它看起来像是slice.indices(n)
返回要提供给的参数range
,以获取应反映在长度序列切片中的项目索引n
(尽管它没有记录在案 编辑:正如@ShadowRanger 指出的那样,它确实被记录在案)。因此,以下几行评估为相同的值:
# 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)))])
Run Code Online (Sandbox Code Playgroud)
如您所见,结果列表的长度与 的长度相同range(*slice(1,15,3).indices(len(my_list)))
,这取决于slice
对象本身以及要切片的序列的长度。这就是为什么len(range(*slice.indices(n)))
会在 Python 3 中为您提供正确答案的原因。(范围对象是一个生成器,幸运的__len__
是它定义了函数,因此它可以为您提供项目计数,而无需枚举和计数它们。)
如果您在 python 2 中处理大量数字,则可以按照@ShadowRanger 的建议复制计算。
的原始实现range.__len__
如下:
# 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)))])
Run Code Online (Sandbox Code Playgroud)
并且slice.indices
:
/* 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;
}
Run Code Online (Sandbox Code Playgroud)
来源来自svn