python range()的切片行为[:]

时间:2019-08-20 15:39:27

标签: python python-3.x slice

我在QC审查中遇到了一些有趣的代码,并对它的行为感到惊讶。我很好奇它是否在任何地方都有记载。

for i in range(0, my_array.max(), 3)[:]:
    # other code here

我对[:]之后是否需要range感到好奇,因此我进行了测试:

>>> range(0, 10, 3)
range(0, 10, 3)
>>> range(0, 10, 3)[:]
range(0, 12, 3)

这些范围定义的实际顺序是相同的,但是我在Python range文档的任何地方都没有看到这种切片行为,所以我很好奇这里的实际情况。

2 个答案:

答案 0 :(得分:3)

让我们假装range仍返回list。切片range对象将返回一个range对象,该对象的作用就像您对基础列表进行切片一样。尽管range对象无需使用列表来执行此操作,但可以使用算术在恒定时间内对其进行处理。

>>> range(0, 90, 2)[10:23]
range(20, 46, 2)

>>> list(range(0, 90, 2)[10:23])
[20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44]

当您执行以下操作时:

range(0, 10, 3)[:]

Python用算术对其进行切片。

我的假设是,在确定最后一个元素时会四舍五入。它尝试计算开始范围内的第零个元素。这将是start + step * 0 = 0

然后Python尝试获取end元素。范围中有(10 - 0) // 3 + 1 = 4个元素,因此结尾元素为start + step * n_elements = 0 + 3 * 4 = 12

答案 1 :(得分:1)

我认为这里有些混杂。

  • range会产生切片行为,因为使用非默认索引切片是有意义的:
>>> list(range(10, 20)[3:7])
[13, 14, 15, 16]
  • 有一个成语是通过产生具有所有默认索引的切片来复制列表(可变的):some_list[:]等同于[x for x in some_list]
  • 有一个奇怪的代码对范围对象(或实际列表,如果是Python 2)执行[:],这使 no 毫无意义。生成的范围对象/列表在其他任何地方都没有被引用。
  • Python文档在名为“序列类型-listtuple range ”的一章中列出了"Common Sequence Operations"之间的切片(示例)。因此已记录在案,但很少有人读过。