【问题标题】:Why can't a range object be used to index a list?为什么不能使用范围对象来索引列表?
【发布时间】:2022-01-24 20:12:55
【问题描述】:

在 Python 3.9 中,不能使用范围对象来索引列表。 确实运行以下代码,第二次打印将返回错误说明“TypeError:列表索引必须是整数或切片,而不是范围”。

x = [1, 2, 3]
s = slice(3)
r = range(3)

print(x[s]) # ok
print(x[r]) # error

这是为什么? Python 解释器不能将范围转换为底层的切片,并将其用于索引吗? 这是因为一些根本原因,还是只是开发人员没有实现(还没有实现?)?

有趣的是,确实可以使用范围索引 numpy 数组!

【问题讨论】:

  • 请注意,numpy 确实ranges 用作slices。比较np.array([1, 2, 3])[range(0, -2)]np.array([1, 2, 3])[slice(0, -2)]。 Numpy 使用 range 来表示它的本质——一个序列。
  • 转换确实是微不足道的(slice(r.start, r.stop, r.step)),但我想不出一个实际情况,你有一个但想要另一个。
  • @MisterMiyagi,谢谢,非常有趣的例子:切片中负数的含义帮助我理解了为什么范围不能提供与切片相同的功能(即索引列表)。如果您想让您的评论成为答案,我很乐意接受。 chepner,谢谢,我知道。 :)

标签: python list indexing range slice


【解决方案1】:

slicerange 是微妙不同的东西,尽管两者都使用 start, stop, step 三元组。如果 Python 默默地使用一个来代替另一个,它可能会导致一些细微的错误。


要直接查看差异,确实可以查看numpy,其中两者导致不同的索引:

>>> arr = np.array([0, 1, 2, 3, 4])
>>> arr[slice(1, -1)]
array([1, 2, 3])
>>> arr[range(1, -1)]
array([], dtype=int64)

结果不同,因为slicerange 对负数的含义不同。

  • range 表示整数 number line 的一部分。这扩展到负数。
  • slice 表示序列的ordinal numbers/ 索引的一部分。1 这会将负数包装回正数。

或者更简单地说,slice 的含义取决于序列的大小,而range 则不然。因此,不小心用一个代替另一个是错误的。


1 从技术上讲,slice 代表start, stop, step任何 概念。标准序列类型将其解释为数字索引。例如,slice 也可以表示图的

【讨论】:

    【解决方案2】:

    range() 确实不是列表也不是元组。它不是用来切片的。

    它实现了类collections.abc.Sequence。它只保存在内存中startstopstep,非常适合内存管理。这里的权衡是您不能执行您可以对列表执行的所有操作,例如切片。但是您可以像这样轻松地将range() 转换为listlist(range(5))

    您可能想阅读更多文档here

    【讨论】:

    • 谢谢,但我的问题实际上是范围与切片有何不同?实际上, slice 也有 start stop 和 step,但是你可以用它来索引列表,而你不能用 range。这可能有一个有意义的设计原因吗?
    • A range 意味着被迭代; slice 对象是从扩展切片语法 ([x:y:z]) 创建的。两者都具有相同的三个属性的事实比其他任何事情都更加巧合。
    猜你喜欢
    • 1970-01-01
    • 2017-06-19
    • 1970-01-01
    • 2015-04-25
    • 2014-06-19
    • 2017-11-11
    • 2021-07-15
    • 2014-04-10
    • 1970-01-01
    相关资源
    最近更新 更多