Terry Reedy wrote: > > John Salerno wrote: > >> Given: > > > numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] > > > can someone explain to me why > > > numbers[10:0:-2] results in [10, 8, 6, 4, 2]? > > It appears that s[i:j:-1] is s[(j+1):(i+1)] .reverse()'ed. For 'numbers', > this is 10, 9, 8, 7, 6, 5, 4, 3, 2]. Then take every other item. Why the > +1? Don't know and not my intuitive expectation. I just know that > extended slicing was developed for and until recently pretty much > restricted to numeric (now numpy). > It's not simply "+1". >>> a = range(10) >>> a[9:0:-2] [9, 7, 5, 3, 1]
>>> a[10:0:-2] [9, 7, 5, 3, 1] >>> a[11:0:-2] [9, 7, 5, 3, 1] >>> a[42:0:-2] [9, 7, 5, 3, 1] > Steven D'Aprano > > I think the documentation is misleading/incomplete when > > it comes to negative strides for extended slices. > > and Andre "Agreed!" also, and you three aren't the only ones. Maybe some > day I will read the source, think about it more, and post a suggested > revision for comment ... or maybe someone will beat me to it. I, myself, think that the slicing behaviour is broken in this case. >From the little I understand (without looking at the source), adjustment on the boundaries of the slicing "request" (the first 2 numbers) is done first, to make them positive and, I believe, ensure that they do not extend beyond the boundaries of the sequence. Then, the actual stepping through is performed. In my (most likely not-well informed enough opinion), the behaviour should be the following: from [i: j: k], if k > 0 and j <= i : return [] if k< 0 and j >= i : return [] otherwise, build the following list of numbers: i, i+k, i+2*k, until i +n*k >= j (if k>0; use <= if k<0) where the last number is excluded, i.e. [0: 2: 1] = list(0, 1) *Then*, exclude from the list just built any negative numbers, or any number greater than the length of the sequence to be sliced. So, [10:0:-2] would yield the following list of numbers [10, 8, 6, 4, 2] before trimming; applying this to range(10), would end up with result in trimming "10" from the list built. Thus, we are looking at indices [8, 6, 4, 2] of range(10), which happen to be the numbers [8, 6, 4, 2] in this case. We should end up with the same list if we ask for [42:0:-2]. This is not the observed behaviour, as we get [9, 7, 5, 3, 1]. If we ask Python to do >>> a[0:10:2] we get [0, 2, 4, 6, 8] which is correct. It seems to me that the following (pseudo-code, not valid Python) a[2:10:2] == a[8:0:-2].reversed() should be true, just like a[1:10:1] == a[9:0:-1].reversed() is true. I *suspect* that "boundary adjustments" are performed first before creating a sequence of indices, so that there is less "trimming" (as described above) for the sake of efficiency ... and that this is not done properly. Then again, perhaps I simply don't understand what slices are supposed to do.... André > > Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list