可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Bear with me while I explain my question. Skip down to the bold heading if you already understand extended slice list indexing.
In python, you can index lists using slice notation. Here's an example:
>>> A = list(range(10))
>>> A[0:5]
[0, 1, 2, 3, 4]
You can also include a stride, which acts like a "step":
>>> A[0:5:2]
[0, 2, 4]
The stride is also allowed to be negative, meaning the elements are retrieved in reverse order:
>>> A[5:0:-1]
[5, 4, 3, 2, 1]
But wait! I wanted to see [4, 3, 2, 1, 0]
. Oh, I see, I need to decrement the start and end indices:
>>> A[4:-1:-1]
[]
What happened? It's interpreting -1 as being at the end of the array, not the beginning. I know you can achieve this as follows:
>>> A[4::-1]
[4, 3, 2, 1, 0]
But you can't use this in all cases. For example, in a method that's been passed indices.
My question is:
Is there any good pythonic way of using extended slices with negative strides and explicit start and end indices that include the first element of a sequence?
This is what I've come up with so far, but it seems unsatisfying.
>>> A[0:5][::-1]
[4, 3, 2, 1, 0]
回答1:
It is error-prone to change the semantics of start
and stop
. Use None
or -(len(a) + 1)
instead of 0
or -1
. The semantics is not arbitrary. See Edsger W. Dijkstra's article "Why numbering should start at zero".
>>> a = range(10)
>>> start, stop, step = 4, None, -1
Or
>>> start, stop, step = 4, -(len(a) + 1), -1
>>> a[start:stop:step]
[4, 3, 2, 1, 0]
Or
>>> s = slice(start, stop, step)
>>> a[s]
[4, 3, 2, 1, 0]
When s
is a sequence the negative indexes in s[i:j:k]
are treated specially:
If i
or j
is negative, the index is relative to the end of the string:
len(s) + i
or len(s) + j
is substituted. But note that -0
is still 0
.
that is why len(range(10)[4:-1:-1]) == 0
because it is equivalent to range(10)[4:9:-1]
.
回答2:
Ok, I think this is probably as good as I will get it. Thanks to Abgan for sparking the idea. This relies on the fact that None in a slice is treated as if it were a missing parameter. Anyone got anything better?
def getReversedList(aList, end, start, step):
return aList[end:start if start!=-1 else None:step]
edit: check for start==-1
, not 0
This is still not ideal, because you're clobbering the usual behavior of -1. It seems the problem here is two overlapping definitions of what's supposed to happen. Whoever wins takes away otherwise valid invocations looking for the other intention.
回答3:
[ A[b] for b in range(end,start,stride) ]
Slower, however you can use negative indices, so this should work:
[ A[b] for b in range(9, -1, -1) ]
I realize this isn't using slices, but thought I'd offer the solution anyway if using slices specifically for getting the result isn't a priority.
回答4:
I believe that the following doesn't satisfy you:
def getReversedList(aList, end, start, step):
if step < 0 and start == 0:
return aList[end::step]
return aList[end:start:step]
or does it? :-)
回答5:
But you can't use that if you are
storing your indices in variables for
example.
Is this satisfactory?
>>> a = range(10)
>>> start = 0
>>> end = 4
>>> a[4:start-1 if start > 0 else None:-1]
[4, 3, 2, 1, 0]
回答6:
As you say very few people fully understand everything that you can do with extended slicing, so unless you really need the extra performance I'd do it the "obvious" way:
rev_subset = reversed(data[start:stop])
回答7:
a[4::-1]
Example:
Python 2.6 (r26:66714, Dec 4 2008, 11:34:15)
[GCC 4.0.1 (Apple Inc. build 5488)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = list(range(10))
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[4:0:-1]
[4, 3, 2, 1]
>>> a[4::-1]
[4, 3, 2, 1, 0]
>>>
The reason is that the second term is interpreted as "while not index ==". Leaving it out is "while index in range".
回答8:
I know this is an old question, but in case someone like me is looking for answers:
>>> A[5-1::-1]
[4, 3, 2, 1, 0]
>>> A[4:1:-1]
[4, 3, 2]
回答9:
You can use a slice(start, stop, step)
object, which is such that
s=slice(start, stop, step)
print a[s]
is the same as
print a[start : stop : step]
and, moreover, you can set any of the arguments to None
to indicate nothing in between the colons. So in the case you give, you can use slice(4, None, -1)
.