我在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文档的任何地方都没有看到这种切片行为,所以我很好奇这里的实际情况。
答案 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]
。[:]
,这使 no 毫无意义。生成的范围对象/列表在其他任何地方都没有被引用。list
,tuple
, range
”的一章中列出了"Common Sequence Operations"之间的切片(示例)。因此已记录在案,但很少有人读过。