The syntax is:
其语法为:
a[start:stop] # items start through stop-1
a[start:] # items start through the rest of the array
a[:stop] # items from the beginning through stop-1
a[:] # a copy of the whole array
There is also the step
value, which can be used with any of the above:
还有步长值,它可以与上面的任一项一起使用:
a[start:stop:step] # start through not past stop, by step
The key point to remember is that the :stop
value represents the first value that is not in the selected slice. So, the difference between stop
and start
is the number of elements selected (if step
is 1, the default).
要记住的关键点是:Stop值表示不在选定切片中的第一个值。因此,STOP和START之间的区别在于所选元素的数量(如果STEP为1,则为默认值)。
The other feature is that start
or stop
may be a negative number, which means it counts from the end of the array instead of the beginning. So:
另一个特点是开始或停止可以是负数,这意味着它从数组的末尾而不是开始计数。所以:
a[-1] # last item in the array
a[-2:] # last two items in the array
a[:-2] # everything except the last two items
Similarly, step
may be a negative number:
类似地,步长可以是负数:
a[::-1] # all items in the array, reversed
a[1::-1] # the first two items, reversed
a[:-3:-1] # the last two items, reversed
a[-3::-1] # everything except the last two items, reversed
Python is kind to the programmer if there are fewer items than you ask for. For example, if you ask for a[:-2]
and a
only contains one element, you get an empty list instead of an error. Sometimes you would prefer the error, so you have to be aware that this may happen.
如果项目比您要求的少,则对程序员来说,这是一种友好的方式。例如,如果您请求一个[:-2],而只包含一个元素,则会得到一个空列表,而不是错误。有时您更喜欢错误,因此您必须意识到这种情况可能会发生。
Relationship with the slice
object
A slice
object can represent a slicing operation, i.e.:
切片对象可以表示切片操作,即:
a[start:stop:step]
is equivalent to:
相当于:
a[slice(start, stop, step)]
Slice objects also behave slightly differently depending on the number of arguments, similarly to range()
, i.e. both slice(stop)
and slice(start, stop[, step])
are supported.
To skip specifying a given argument, one might use None
, so that e.g. a[start:]
is equivalent to a[slice(start, None)]
or a[::-1]
is equivalent to a[slice(None, None, -1)]
.
切片对象的行为也略有不同,具体取决于参数的数量,类似于Range(),即同时支持Slice(停止)和Slice(Start,Stop[,Step])。要跳过指定给定参数,可以使用NONE,例如,[START:]等同于[Slice(Start,None)],或者[::-1]等同于[Slice(None,None,-1)]。
While the :
-based notation is very helpful for simple slicing, the explicit use of slice()
objects simplifies the programmatic generation of slicing.
虽然基于:的表示法对简单切片非常有帮助,但明确使用Slice()对象简化了切片的编程生成。
The Python tutorial talks about it (scroll down a bit until you get to the part about slicing).
在Python教程中将会讨论到这一点(向下滚动一点,直到您看到关于切片的部分)。
The ASCII art diagram is helpful too for remembering how slices work:
ASCII图表对于记住切片的工作原理也很有帮助:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
One way to remember how slices work is to think of the indices as pointing between characters, with the left edge of the first character numbered 0. Then the right edge of the last character of a string of n characters has index n.
Enumerating the possibilities allowed by the grammar for the sequence x
:
列举序列x的语法所允许的可能性:
>>> x[:] # [x[0], x[1], ..., x[-1] ]
>>> x[low:] # [x[low], x[low+1], ..., x[-1] ]
>>> x[:high] # [x[0], x[1], ..., x[high-1]]
>>> x[low:high] # [x[low], x[low+1], ..., x[high-1]]
>>> x[::stride] # [x[0], x[stride], ..., x[-1] ]
>>> x[low::stride] # [x[low], x[low+stride], ..., x[-1] ]
>>> x[:high:stride] # [x[0], x[stride], ..., x[high-1]]
>>> x[low:high:stride] # [x[low], x[low+stride], ..., x[high-1]]
Of course, if (high-low)%stride != 0
, then the end point will be a little lower than high-1
.
当然,如果(高-低)%Stride!=0,则终点将略低于高-1。
If stride
is negative, the ordering is changed a bit since we're counting down:
如果Stride为负数,则排序会稍有更改,因为我们正在倒计时:
>>> x[::-stride] # [x[-1], x[-1-stride], ..., x[0] ]
>>> x[high::-stride] # [x[high], x[high-stride], ..., x[0] ]
>>> x[:low:-stride] # [x[-1], x[-1-stride], ..., x[low+1]]
>>> x[high:low:-stride] # [x[high], x[high-stride], ..., x[low+1]]
Extended slicing (with commas and ellipses) are mostly used only by special data structures (like NumPy); the basic sequences don't support them.
扩展切片(带有逗号和省略号)主要由特殊数据结构(如NumPy)使用;基本序列不支持它们。
>>> class slicee:
... def __getitem__(self, item):
... return repr(item)
...
>>> slicee()[0, 1:2, ::5, ...]
'(0, slice(1, 2, None), slice(None, None, 5), Ellipsis)'
The answers above don't discuss slice assignment. To understand slice assignment, it's helpful to add another concept to the ASCII art:
上面的答案没有讨论切片分配。要理解切片赋值,向ASCII技术添加另一个概念是很有帮助的:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
Slice position: 0 1 2 3 4 5 6
Index position: 0 1 2 3 4 5
>>> p = ['P','y','t','h','o','n']
# Why the two sets of numbers:
# indexing gives items, not lists
>>> p[0]
'P'
>>> p[5]
'n'
# Slicing gives lists
>>> p[0:1]
['P']
>>> p[0:2]
['P','y']
One heuristic is, for a slice from zero to n, think: "zero is the beginning, start at the beginning and take n items in a list".
一种启发式的方法是,对于一个从零到n的切片,想一想:“零是开始,从开始开始,在一个列表中取n个项目”。
>>> p[5] # the last of six items, indexed from zero
'n'
>>> p[0:5] # does NOT include the last item!
['P','y','t','h','o']
>>> p[0:6] # not p[0:5]!!!
['P','y','t','h','o','n']
Another heuristic is, "for any slice, replace the start by zero, apply the previous heuristic to get the end of the list, then count the first number back up to chop items off the beginning"
另一种启发式方法是,“对于任何切片,用零代替开头,应用前面的启发式方法得到列表的末尾,然后倒数第一个数字,把条目从开头砍掉。”
>>> p[0:4] # Start at the beginning and count out 4 items
['P','y','t','h']
>>> p[1:4] # Take one item off the front
['y','t','h']
>>> p[2:4] # Take two items off the front
['t','h']
# etc.
The first rule of slice assignment is that since slicing returns a list, slice assignment requires a list (or other iterable):
切片分配的第一条规则是,由于切片返回一个列表,因此切片分配需要一个列表(或其他可迭代的):
>>> p[2:3]
['t']
>>> p[2:3] = ['T']
>>> p
['P','y','T','h','o','n']
>>> p[2:3] = 't'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only assign an iterable
The second rule of slice assignment, which you can also see above, is that whatever portion of the list is returned by slice indexing, that's the same portion that is changed by slice assignment:
切片分配的第二条规则(您也可以在上面看到)是,切片索引返回列表的任何部分,也就是切片分配更改的部分:
>>> p[2:4]
['T','h']
>>> p[2:4] = ['t','r']
>>> p
['P','y','t','r','o','n']
The third rule of slice assignment is, the assigned list (iterable) doesn't have to have the same length; the indexed slice is simply sliced out and replaced en masse by whatever is being assigned:
片分配的第三条规则是,分配的列表(可迭代)不必具有相同的长度;索引片被简单地切出来,并被分配的内容整体替换:
>>> p = ['P','y','t','h','o','n'] # Start over
>>> p[2:4] = ['s','p','a','m']
>>> p
['P','y','s','p','a','m','o','n']
The trickiest part to get used to is assignment to empty slices. Using heuristic 1 and 2 it's easy to get your head around indexing an empty slice:
最难习惯的部分是对空片的赋值。使用启发式1和2,您可以很容易地对一个空片进行索引:
>>> p = ['P','y','t','h','o','n']
>>> p[0:4]
['P','y','t','h']
>>> p[1:4]
['y','t','h']
>>> p[2:4]
['t','h']
>>> p[3:4]
['h']
>>> p[4:4]
[]
And then once you've seen that, slice assignment to the empty slice makes sense too:
然后,一旦您看到了这一点,将切片分配给空切片也是有意义的:
>>> p = ['P','y','t','h','o','n']
>>> p[2:4] = ['x','y'] # Assigned list is same length as slice
>>> p
['P','y','x','y','o','n'] # Result is same length
>>> p = ['P','y','t','h','o','n']
>>> p[3:4] = ['x','y'] # Assigned list is longer than slice
>>> p
['P','y','t','x','y','o','n'] # The result is longer
>>> p = ['P','y','t','h','o','n']
>>> p[4:4] = ['x','y']
>>> p
['P','y','t','h','x','y','o','n'] # The result is longer still
Note that, since we are not changing the second number of the slice (4), the inserted items always stack right up against the 'o', even when we're assigning to the empty slice. So the position for the empty slice assignment is the logical extension of the positions for the non-empty slice assignments.
请注意,由于我们不会更改切片的第二个编号(4),因此插入的项始终堆叠在‘o’的正上方,即使我们为空切片赋值。因此,用于空片分配的位置是用于非空片分配的位置的逻辑扩展。
Backing up a little bit, what happens when you keep going with our procession of counting up the slice beginning?
倒回去一点,当你继续我们开始计算切片的过程时会发生什么?
>>> p = ['P','y','t','h','o','n']
>>> p[0:4]
['P','y','t','h']
>>> p[1:4]
['y','t','h']
>>> p[2:4]
['t','h']
>>> p[3:4]
['h']
>>> p[4:4]
[]
>>> p[5:4]
[]
>>> p[6:4]
[]
With slicing, once you're done, you're done; it doesn't start slicing backwards. In Python you don't get negative strides unless you explicitly ask for them by using a negative number.
有了切片,一旦你完成了,你就完成了;它不会开始向后切片。在Python中,除非您使用负数显式请求,否则不会得到负步长。
>>> p[5:3:-1]
['n','o']
There are some weird consequences to the "once you're done, you're done" rule:
“一旦你做完了,你就做完了”这条规则有一些奇怪的后果:
>>> p[4:4]
[]
>>> p[5:4]
[]
>>> p[6:4]
[]
>>> p[6]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
In fact, compared to indexing, Python slicing is bizarrely error-proof:
事实上,与索引相比,Python切片是奇怪的防错:
>>> p[100:200]
[]
>>> p[int(2e99):int(1e99)]
[]
This can come in handy sometimes, but it can also lead to somewhat strange behavior:
这有时会派上用场,但也会导致一些奇怪的行为:
>>> p
['P', 'y', 't', 'h', 'o', 'n']
>>> p[int(2e99):int(1e99)] = ['p','o','w','e','r']
>>> p
['P', 'y', 't', 'h', 'o', 'n', 'p', 'o', 'w', 'e', 'r']
Depending on your application, that might... or might not... be what you were hoping for there!
根据您的应用程序,这可能会...或许不会..。做你在那里所希望的吧!
Below is the text of my original answer. It has been useful to many people, so I didn't want to delete it.
以下是我最初回答的文本。它对很多人都很有用,所以我不想把它删除。
>>> r=[1,2,3,4]
>>> r[1:1]
[]
>>> r[1:1]=[9,8]
>>> r
[1, 9, 8, 2, 3, 4]
>>> r[1:1]=['blah']
>>> r
[1, 'blah', 9, 8, 2, 3, 4]
This may also clarify the difference between slicing and indexing.
这也可能澄清切片和索引之间的区别。
Explain Python's slice notation
In short, the colons (:
) in subscript notation (subscriptable[subscriptarg]
) make slice notation, which has the optional arguments start
, stop
, and step
:
简而言之,下标表示法中的冒号(:)构成切片表示法,它有可选的参数START、STOP和STEP:
sliceable[start:stop:step]
Python slicing is a computationally fast way to methodically access parts of your data. In my opinion, to be even an intermediate Python programmer, it's one aspect of the language that it is necessary to be familiar with.
Python切片是有条不紊地访问部分数据的一种计算速度很快的方法。在我看来,即使是一个中级的Python程序员,这也是必须熟悉的语言的一个方面。
Important Definitions
To begin with, let's define a few terms:
首先,让我们定义几个术语:
start
: the beginning index of the slice, it will include the element at this index unless it is the same as stop, defaults to 0, i.e. the first index. If it's negative, it means to start n
items from the end.
stop
: the ending index of the slice, it does not include the element at this index, defaults to length of the sequence being sliced, that is, up to and including the end.
step
: the amount by which the index increases, defaults to 1. If it's negative, you're slicing over the iterable in reverse.
How Indexing Works
You can make any of these positive or negative numbers. The meaning of the positive numbers is straightforward, but for negative numbers, just like indexes in Python, you count backwards from the end for the start and stop, and for the step, you simply decrement your index. This example is from the documentation's tutorial, but I've modified it slightly to indicate which item in a sequence each index references:
您可以使这些数字中的任何一个为正数或负数。正数的含义很简单,但是对于负数,就像在Python中的索引一样,您从末尾开始和结束时向后计数,而对于步骤,您只需递减索引即可。此示例摘自文档教程,但我对其稍作了修改,以指示每个索引引用序列中的哪一项:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5
-6 -5 -4 -3 -2 -1
How Slicing Works
To use slice notation with a sequence that supports it, you must include at least one colon in the square brackets that follow the sequence (which actually implement the __getitem__
method of the sequence, according to the Python data model.)
要在支持切片表示法的序列中使用切片表示法,必须在序列后面的方括号中至少包含一个冒号(根据Python数据模型,它实际上实现了序列的__getitem__方法)。
Slice notation works like this:
切片表示法的工作原理如下:
sequence[start:stop:step]
And recall that there are defaults for start, stop, and step, so to access the defaults, simply leave out the argument.
记住,Start、Stop和Step都有缺省值,因此要访问缺省值,只需省略参数即可。
Slice notation to get the last nine elements from a list (or any other sequence that supports it, like a string) would look like this:
切片表示法用于获取列表(或任何其他支持它的序列,如字符串)中的最后九个元素,如下所示:
my_list[-9:]
When I see this, I read the part in the brackets as "9th from the end, to the end." (Actually, I abbreviate it mentally as "-9, on")
当我看到这一点时,我把括号里的部分读成了“第9个从最后,到最后”。(实际上,我在心里把它缩写为“-9,on”)
Explanation:
The full notation is
完整的符号是
my_list[-9:None:None]
and to substitute the defaults (actually when step
is negative, stop
's default is -len(my_list) - 1
, so None
for stop really just means it goes to whichever end step takes it to):
并替换缺省值(实际上,当步骤为负时,STOP的缺省值为-len(My_List)-1,因此NONE实际上只是表示它将转到任何结束步骤):
my_list[-9:len(my_list):1]
The colon, :
, is what tells Python you're giving it a slice and not a regular index. That's why the idiomatic way of making a shallow copy of lists in Python 2 is
冒号:告诉Python你给它一个切片而不是一个常规索引。这就是为什么在Python 2中制作列表的浅拷贝的惯用方法是
list_copy = sequence[:]
And clearing them is with:
而清除它们的方法是:
del my_list[:]
(Python 3 gets a list.copy
and list.clear
method.)
(Python3获得了一个list.Copy和list.lear方法。)
When step
is negative, the defaults for start
and stop
change
By default, when the step
argument is empty (or None
), it is assigned to +1
.
默认情况下,当步骤参数为空(或无)时,会将其指定为+1。
But you can pass in a negative integer, and the list (or most other standard sliceables) will be sliced from the end to the beginning.
但您可以传入一个负整数,列表(或大多数其他标准切片)将从末尾切片到开头。
Thus a negative slice will change the defaults for start
and stop
!
因此,负值切片将更改启动和停止的默认设置!
Confirming this in the source
I like to encourage users to read the source as well as the documentation. The source code for slice objects and this logic is found here. First we determine if step
is negative:
我喜欢鼓励用户阅读源代码和文档。切片对象的源代码和这个逻辑可以在这里找到。首先,我们确定步骤是否为负数:
step_is_negative = step_sign < 0;
If so, the lower bound is -1
meaning we slice all the way up to and including the beginning, and the upper bound is the length minus 1, meaning we start at the end. (Note that the semantics of this -1
is different from a -1
that users may pass indexes in Python indicating the last item.)
如果是这样的话,下限是-1,这意味着我们一直切片到并包括开头,而上限是长度减1,这意味着我们从结尾开始。(请注意,this-1的语义与-1不同,后者用户可以在Python中传递指示最后一项的索引。)
if (step_is_negative) {
lower = PyLong_FromLong(-1L);
if (lower == NULL)
goto error;
upper = PyNumber_Add(length, lower);
if (upper == NULL)
goto error;
}
Otherwise step
is positive, and the lower bound will be zero and the upper bound (which we go up to but not including) the length of the sliced list.
否则,步骤为正,并且下限将为零,而上限(我们向上到达,但不包括)将是切片列表的长度。
else {
lower = _PyLong_Zero;
Py_INCREF(lower);
upper = length;
Py_INCREF(upper);
}
Then, we may need to apply the defaults for start
and stop
—the default then for start
is calculated as the upper bound when step
is negative:
然后,我们可能需要应用Start和Stop的默认值-当Step为负值时,Start的默认值Then被计算为上限:
if (self->start == Py_None) {
start = step_is_negative ? upper : lower;
Py_INCREF(start);
}
and stop
, the lower bound:
止步,下限:
if (self->stop == Py_None) {
stop = step_is_negative ? lower : upper;
Py_INCREF(stop);
}
Give your slices a descriptive name!
You may find it useful to separate forming the slice from passing it to the list.__getitem__
method (that's what the square brackets do). Even if you're not new to it, it keeps your code more readable so that others that may have to read your code can more readily understand what you're doing.
您可能会发现,将形成切片与将其传递给列表分开是很有用的。__getitem__方法(这就是方括号所做的工作)。即使您对它并不陌生,它也会使您的代码更具可读性,以便其他可能需要阅读您的代码的人能够更容易地理解您在做什么。
However, you can't just assign some integers separated by colons to a variable. You need to use the slice object:
但是,您不能只将一些用冒号分隔的整数赋给变量。您需要使用Slice对象:
last_nine_slice = slice(-9, None)
The second argument, None
, is required, so that the first argument is interpreted as the start
argument otherwise it would be the stop
argument.
第二个参数None是必需的,因此第一个参数将被解释为Start参数,否则它将是Stop参数。
You can then pass the slice object to your sequence:
然后可以将切片对象传递给您的序列:
>>> list(range(100))[last_nine_slice]
[91, 92, 93, 94, 95, 96, 97, 98, 99]
It's interesting that ranges also take slices:
有趣的是,Range也会分成几部分:
>>> range(100)[last_nine_slice]
range(91, 100)
Memory Considerations:
Since slices of Python lists create new objects in memory, another important function to be aware of is itertools.islice
. Typically you'll want to iterate over a slice, not just have it created statically in memory. islice
is perfect for this. A caveat, it doesn't support negative arguments to start
, stop
, or step
, so if that's an issue you may need to calculate indices or reverse the iterable in advance.
由于Python列表的片段会在内存中创建新对象,因此需要注意的另一个重要函数是itertools.islice。通常,您会希望在片上迭代,而不仅仅是在内存中静态创建它。斯莱斯非常适合这一点。需要注意的是,它不支持开始、停止或步进的负参数,因此如果这是一个问题,您可能需要提前计算索引或反转可迭代。
length = 100
last_nine_iter = itertools.islice(list(range(length)), length-9, None, 1)
list_last_nine = list(last_nine_iter)
and now:
而现在:
>>> list_last_nine
[91, 92, 93, 94, 95, 96, 97, 98, 99]
The fact that list slices make a copy is a feature of lists themselves. If you're slicing advanced objects like a Pandas DataFrame, it may return a view on the original, and not a copy.
列表切片复制的事实是列表本身的一个特性。如果您正在切片高级对象,如Pandas DataFrame,它可能会返回原始对象的视图,而不是副本。
And a couple of things that weren't immediately obvious to me when I first saw the slicing syntax:
当我第一次看到切片语法时,有几件事对我来说并不是很明显:
>>> x = [1,2,3,4,5,6]
>>> x[::-1]
[6,5,4,3,2,1]
Easy way to reverse sequences!
简单的方法来扭转序列!
And if you wanted, for some reason, every second item in the reversed sequence:
如果你想,出于某种原因,倒序的每两个项目:
>>> x = [1,2,3,4,5,6]
>>> x[::-2]
[6,4,2]
In Python 2.7
在Python2.7中
Slicing in Python
在Python中进行切片
[a:b:c]
len = length of string, tuple or list
c -- default is +1. The sign of c indicates forward or backward, absolute value of c indicates steps. Default is forward with step size 1. Positive means forward, negative means backward.
a -- When c is positive or blank, default is 0. When c is negative, default is -1.
b -- When c is positive or blank, default is len. When c is negative, default is -(len+1).
Understanding index assignment is very important.
理解索引分配是非常重要的。
In forward direction, starts at 0 and ends at len-1
In backward direction, starts at -1 and ends at -len
When you say [a:b:c], you are saying depending on the sign of c (forward or backward), start at a and end at b (excluding element at bth index). Use the indexing rule above and remember you will only find elements in this range:
当你说[a:b:c]时,你是说取决于c的符号(向前或向后),从a开始,到b结束(不包括第bth索引的元素)。使用上面的索引规则,请记住,您只能找到此范围内的元素:
-len, -len+1, -len+2, ..., 0, 1, 2,3,4 , len -1
But this range continues in both directions infinitely:
但这一范围在两个方向上都会无限延续:
...,-len -2 ,-len-1,-len, -len+1, -len+2, ..., 0, 1, 2,3,4 , len -1, len, len +1, len+2 , ....
For example:
例如:
0 1 2 3 4 5 6 7 8 9 10 11
a s t r i n g
-9 -8 -7 -6 -5 -4 -3 -2 -1
If your choice of a, b, and c allows overlap with the range above as you traverse using rules for a,b,c above you will either get a list with elements (touched during traversal) or you will get an empty list.
如果您选择的a、b和c允许在使用上面的a、b、c规则进行遍历时与上面的范围重叠,您将获得一个包含元素的列表(在遍历过程中被触及),或者您将获得一个空列表。
One last thing: if a and b are equal, then also you get an empty list:
最后一件事:如果a和b相等,那么你也会得到一个空的列表:
>>> l1
[2, 3, 4]
>>> l1[:]
[2, 3, 4]
>>> l1[::-1] # a default is -1 , b default is -(len+1)
[4, 3, 2]
>>> l1[:-4:-1] # a default is -1
[4, 3, 2]
>>> l1[:-3:-1] # a default is -1
[4, 3]
>>> l1[::] # c default is +1, so a default is 0, b default is len
[2, 3, 4]
>>> l1[::-1] # c is -1 , so a default is -1 and b default is -(len+1)
[4, 3, 2]
>>> l1[-100:-200:-1] # Interesting
[]
>>> l1[-1:-200:-1] # Interesting
[4, 3, 2]
>>> l1[-1:-1:1]
[]
>>> l1[-1:5:1] # Interesting
[4]
>>> l1[1:-7:1]
[]
>>> l1[1:-7:-1] # Interesting
[3, 2]
>>> l1[:-2:-2] # a default is -1, stop(b) at -2 , step(c) by 2 in reverse direction
[4]
Found this great table at http://wiki.python.org/moin/MovingToPythonFromOtherLanguages
在http://wiki.python.org/moin/MovingToPythonFromOtherLanguages找到了一张很棒的桌子
Python indexes and slices for a six-element list.
Indexes enumerate the elements, slices enumerate the spaces between the elements.
Index from rear: -6 -5 -4 -3 -2 -1 a=[0,1,2,3,4,5] a[1:]==[1,2,3,4,5]
Index from front: 0 1 2 3 4 5 len(a)==6 a[:5]==[0,1,2,3,4]
+---+---+---+---+---+---+ a[0]==0 a[:-2]==[0,1,2,3]
| a | b | c | d | e | f | a[5]==5 a[1:2]==[1]
+---+---+---+---+---+---+ a[-1]==5 a[1:-1]==[1,2,3,4]
Slice from front: : 1 2 3 4 5 : a[-2]==4
Slice from rear: : -5 -4 -3 -2 -1 :
b=a[:]
b==[0,1,2,3,4,5] (shallow copy of a)
After using it a bit I realise that the simplest description is that it is exactly the same as the arguments in a for
loop...
在使用了一下之后,我意识到最简单的描述就是它与for循环中的参数完全相同……
(from:to:step)
Any of them are optional:
它们中的任何一个都是可选的:
(:to:step)
(from::step)
(from:to)
Then the negative indexing just needs you to add the length of the string to the negative indices to understand it.
然后,负索引只需要将字符串的长度与负索引相加,就可以理解它。
This works for me anyway...
不管怎样,这对我来说很管用。
I find it easier to remember how it works, and then I can figure out any specific start/stop/step combination.
我发现更容易记住它是如何工作的,然后我就可以计算出任何特定的开始/停止/步骤组合。
It's instructive to understand range()
first:
首先了解Range()很有帮助:
def range(start=0, stop, step=1): # Illegal syntax, but that's the effect
i = start
while (i < stop if step > 0 else i > stop):
yield i
i += step
Begin from start
, increment by step
, do not reach stop
. Very simple.
从头开始,一步一步地递增,不要到达终点。非常简单。
The thing to remember about negative step is that stop
is always the excluded end, whether it's higher or lower. If you want same slice in opposite order, it's much cleaner to do the reversal separately: e.g. 'abcde'[1:-2][::-1]
slices off one char from left, two from right, then reverses. (See also reversed()
.)
关于负步,需要记住的是,止损总是被排除在外的终点,无论它是高还是低。如果您想以相反的顺序使用相同的切片,则单独执行反转要干净得多:例如,‘abcde’[1:-2][::-1]从左侧切下一个字符,从右侧切下两个字符,然后反转。(另请参阅反转()。)
Sequence slicing is same, except it first normalizes negative indexes, and it can never go outside the sequence:
序列切片是相同的,除了它首先规范化负索引,并且它永远不会超出序列:
TODO: The code below had a bug with "never go outside the sequence" when abs(step)>1; I think I patched it to be correct, but it's hard to understand.
TODO:当abs(Step)>1时,下面的代码有一个错误,那就是“永远不要走出顺序”;我想我把它打上补丁是正确的,但它很难理解。
def this_is_how_slicing_works(seq, start=None, stop=None, step=1):
if start is None:
start = (0 if step > 0 else len(seq)-1)
elif start < 0:
start += len(seq)
if not 0 <= start < len(seq): # clip if still outside bounds
start = (0 if step > 0 else len(seq)-1)
if stop is None:
stop = (len(seq) if step > 0 else -1) # really -1, not last element
elif stop < 0:
stop += len(seq)
for i in range(start, stop, step):
if 0 <= i < len(seq):
yield seq[i]
Don't worry about the is None
details - just remember that omitting start
and/or stop
always does the right thing to give you the whole sequence.
不要担心IS NONE的细节--只需记住省略START和/或STOP总是正确的,可以给出整个序列。
Normalizing negative indexes first allows start and/or stop to be counted from the end independently: 'abcde'[1:-2] == 'abcde'[1:3] == 'bc'
despite range(1,-2) == []
.
The normalization is sometimes thought of as "modulo the length", but note it adds the length just once: e.g. 'abcde'[-53:42]
is just the whole string.
首先规格化负索引允许开始和/或停止从末尾独立计数:‘ABCDE’[1:-2]==‘abcde’[1:3]==‘BC’,不管Range(1,-2)==[]。规格化有时被认为是“对长度取模”,但请注意,它只添加一次长度:例如,‘abcde’[-53:42]就是整个字符串。
I use the "an index points between elements" method of thinking about it myself, but one way of describing it which sometimes helps others get it is this:
我自己使用“元素间的索引点”的方法来思考它,但描述它的一种方法有时会帮助其他人理解它,这是这样的:
mylist[X:Y]
X is the index of the first element you want.
Y is the index of the first element you don't want.
X是您想要的第一个元素的索引。Y是您不想要的第一个元素的索引。
Index:
------------>
0 1 2 3 4
+---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
0 -4 -3 -2 -1
<------------
Slice:
<---------------|
|--------------->
: 1 2 3 4 :
+---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
: -4 -3 -2 -1 :
|--------------->
<---------------|
I hope this will help you to model the list in Python.
我希望这将帮助您用Python语言对列表进行建模。
Reference: http://wiki.python.org/moin/MovingToPythonFromOtherLanguages
参考文献:http://wiki.python.org/moin/MovingToPythonFromOtherLanguages
This is how I teach slices to newbies:
这就是我教新手切面的方法:
Understanding the difference between indexing and slicing:
了解索引和切片之间的区别:
Wiki Python has this amazing picture which clearly distinguishes indexing and slicing.
Wiki Python有一张令人惊叹的图片,它清楚地区分了索引和切片。
It is a list with six elements in it. To understand slicing better, consider that list as a set of six boxes placed together. Each box has an alphabet in it.
这是一个包含六个元素的列表。为了更好地理解切片,请将该列表视为一组放在一起的六个盒子。每个盒子里都有一个字母表。
Indexing is like dealing with the contents of box. You can check contents of any box. But you can't check the contents of multiple boxes at once. You can even replace the contents of the box. But you can't place two balls in one box or replace two balls at a time.
索引就像处理盒子里的东西一样。您可以检查任何框中的内容。但你不能一次检查多个盒子里的东西。你甚至可以更换盒子里的东西。但你不能把两个球放在一个盒子里,或者一次换两个球。
In [122]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']
In [123]: alpha
Out[123]: ['a', 'b', 'c', 'd', 'e', 'f']
In [124]: alpha[0]
Out[124]: 'a'
In [127]: alpha[0] = 'A'
In [128]: alpha
Out[128]: ['A', 'b', 'c', 'd', 'e', 'f']
In [129]: alpha[0,1]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-129-c7eb16585371> in <module>()
----> 1 alpha[0,1]
TypeError: list indices must be integers, not tuple
Slicing is like dealing with boxes themselves. You can pick up the first box and place it on another table. To pick up the box, all you need to know is the position of beginning and ending of the box.
切片就像处理盒子本身一样。你可以拿起第一个盒子,把它放在另一张桌子上。要拿起盒子,你只需要知道盒子的开始和结束的位置。
You can even pick up the first three boxes or the last two boxes or all boxes between 1 and 4. So, you can pick any set of boxes if you know the beginning and ending. These positions are called start and stop positions.
你甚至可以选择前三个盒子,或者最后两个盒子,或者1到4之间的所有盒子。所以,如果你知道开始和结束,你可以选择任何一组盒子。这些位置称为开始位置和停止位置。
The interesting thing is that you can replace multiple boxes at once. Also you can place multiple boxes wherever you like.
有趣的是,你可以一次更换多个盒子。你也可以把多个盒子放在你喜欢的任何地方。
In [130]: alpha[0:1]
Out[130]: ['A']
In [131]: alpha[0:1] = 'a'
In [132]: alpha
Out[132]: ['a', 'b', 'c', 'd', 'e', 'f']
In [133]: alpha[0:2] = ['A', 'B']
In [134]: alpha
Out[134]: ['A', 'B', 'c', 'd', 'e', 'f']
In [135]: alpha[2:2] = ['x', 'xx']
In [136]: alpha
Out[136]: ['A', 'B', 'x', 'xx', 'c', 'd', 'e', 'f']
Slicing With Step:
使用STEP进行切片:
Till now you have picked boxes continuously. But sometimes you need to pick up discretely. For example, you can pick up every second box. You can even pick up every third box from the end. This value is called step size. This represents the gap between your successive pickups. The step size should be positive if You are picking boxes from the beginning to end and vice versa.
到现在为止,你一直在挑选箱子。但有时你需要小心翼翼地拿起。例如,您可以每隔一段时间拿起一个盒子。你甚至可以从最后拿起每三个盒子。该值称为步长。这代表了两次接听之间的间隔。如果从头到尾拾取长方体,步长应为正数,反之亦然。
In [137]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']
In [142]: alpha[1:5:2]
Out[142]: ['b', 'd']
In [143]: alpha[-1:-5:-2]
Out[143]: ['f', 'd']
In [144]: alpha[1:5:-2]
Out[144]: []
In [145]: alpha[-1:-5:2]
Out[145]: []
How Python Figures Out Missing Parameters:
Python如何找出缺少的参数:
When slicing, if you leave out any parameter, Python tries to figure it out automatically.
在切片时,如果您遗漏了任何参数,则Python会尝试自动找出它。
If you check the source code of CPython, you will find a function called PySlice_GetIndicesEx() which figures out indices to a slice for any given parameters. Here is the logical equivalent code in Python.
如果查看CPython的源代码,您会发现一个名为PySlice_GetIndicesEx()的函数,它计算出任何给定参数的片的索引。下面是用Python语言编写的逻辑等价代码。
This function takes a Python object and optional parameters for slicing and returns the start, stop, step, and slice length for the requested slice.
此函数接受一个Python对象和用于切片的可选参数,并返回所请求切片的开始、停止、步长和切片长度。
def py_slice_get_indices_ex(obj, start=None, stop=None, step=None):
length = len(obj)
if step is None:
step = 1
if step == 0:
raise Exception("Step cannot be zero.")
if start is None:
start = 0 if step > 0 else length - 1
else:
if start < 0:
start += length
if start < 0:
start = 0 if step > 0 else -1
if start >= length:
start = length if step > 0 else length - 1
if stop is None:
stop = length if step > 0 else -1
else:
if stop < 0:
stop += length
if stop < 0:
stop = 0 if step > 0 else -1
if stop >= length:
stop = length if step > 0 else length - 1
if (step < 0 and stop >= start) or (step > 0 and start >= stop):
slice_length = 0
elif step < 0:
slice_length = (stop - start + 1)/(step) + 1
else:
slice_length = (stop - start - 1)/(step) + 1
return (start, stop, step, slice_length)
This is the intelligence that is present behind slices. Since Python has an built-in function called slice, you can pass some parameters and check how smartly it calculates missing parameters.
这就是存在于切片背后的智能。由于Python有一个名为Slice的内置函数,因此您可以传递一些参数,并检查它计算缺失参数的准确性。
In [21]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']
In [22]: s = slice(None, None, None)
In [23]: s
Out[23]: slice(None, None, None)
In [24]: s.indices(len(alpha))
Out[24]: (0, 6, 1)
In [25]: range(*s.indices(len(alpha)))
Out[25]: [0, 1, 2, 3, 4, 5]
In [26]: s = slice(None, None, -1)
In [27]: range(*s.indices(len(alpha)))
Out[27]: [5, 4, 3, 2, 1, 0]
In [28]: s = slice(None, 3, -1)
In [29]: range(*s.indices(len(alpha)))
Out[29]: [5, 4]
Note: This post was originally written in my blog, The Intelligence Behind Python Slices.
注:这篇文章最初是在我的博客《Python切片背后的智能》中写的。
Python slicing notation:
Python切片表示法:
a[start:end:step]
- For
start
and end
, negative values are interpreted as being relative to the end of the sequence.
- Positive indices for
end
indicate the position after the last element to be included.
- Blank values are defaulted as follows:
[+0:-0:1]
.
- Using a negative step reverses the interpretation of
start
and end
The notation extends to (numpy) matrices and multidimensional arrays. For example, to slice entire columns you can use:
该符号扩展到(NumPy)矩阵和多维数组。例如,要切片整个列,您可以使用:
m[::,0:2:] ## slice the first two columns
Slices hold references, not copies, of the array elements. If you want to make a separate copy an array, you can use deepcopy()
.
切片保存数组元素的引用,而不是副本。如果要为数组创建单独的副本,可以使用DeepCopy()。
You can also use slice assignment to remove one or more elements from a list:
还可以使用切片分配从列表中删除一个或多个元素:
r = [1, 'blah', 9, 8, 2, 3, 4]
>>> r[1:4] = []
>>> r
[1, 2, 3, 4]
This is just for some extra info...
Consider the list below
这只是一些额外的信息..。考虑一下下面的列表
>>> l=[12,23,345,456,67,7,945,467]
Few other tricks for reversing the list:
以下是颠倒榜单的几个小窍门:
>>> l[len(l):-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]
>>> l[:-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]
>>> l[len(l)::-1]
[467, 945, 7, 67, 456, 345, 23, 12]
>>> l[::-1]
[467, 945, 7, 67, 456, 345, 23, 12]
>>> l[-1:-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]
1. Slice Notation
To make it simple, remember slice has only one form:
为了简单起见,请记住Slice只有一种形式:
s[start:end:step]
and here is how it works:
下面是它的工作原理:
s
: an object that can be sliced
start
: first index to start iteration
end
: last index, NOTE that end
index will not be included in the resulted slice
step
: pick element every step
index
Another import thing: all start
,end
, step
can be omitted! And if they are omitted, their default value will be used: 0
,len(s)
,1
accordingly.
另一个重要的事情:所有的开始,结束,步骤可以省略!如果它们被省略,它们的默认值将被使用:0,len(s),1。
So possible variations are:
因此,可能的变化有:
# Mostly used variations
s[start:end]
s[start:]
s[:end]
# Step-related variations
s[:end:step]
s[start::step]
s[::step]
# Make a copy
s[:]
NOTE: If start >= end
(considering only when step>0
), Python will return a empty slice []
.
注意:如果Start>=End(仅当步骤>0时才考虑),则Python将返回空片[]。
2. Pitfalls
The above part explains the core features on how slice works, and it will work on most occasions. However, there can be pitfalls you should watch out, and this part explains them.
上面的部分解释了Slice如何工作的核心特性,它将在大多数情况下工作。然而,也可能存在您应该注意的陷阱,这一部分对此进行了解释。
Negative indexes
The very first thing that confuses Python learners is that an index can be negative!
Don't panic: a negative index means count backwards.
第一件让Python学习者感到困惑的事情是索引可以是负数!不要惊慌:负指数意味着倒数。
For example:
例如:
s[-5:] # Start at the 5th index from the end of array,
# thus returning the last 5 elements.
s[:-5] # Start at index 0, and end until the 5th index from end of array,
# thus returning s[0:len(s)-5].
Negative step
Making things more confusing is that step
can be negative too!
更令人困惑的是,这一步也可能是负面的!
A negative step means iterate the array backwards: from the end to start, with the end index included, and the start index excluded from the result.
负步长意味着向后遍历数组:从末尾到开头,包括末尾索引,从结果中排除起始索引。
NOTE: when step is negative, the default value for start
is len(s)
(while end
does not equal to 0
, because s[::-1]
contains s[0]
). For example:
注:当Step为负值时,Start的默认值为len(S)(End不等于0,因为S[::-1]包含S[0])。例如:
s[::-1] # Reversed slice
s[len(s)::-1] # The same as above, reversed slice
s[0:len(s):-1] # Empty list
Out of range error?
Be surprised: slice does not raise an IndexError when the index is out of range!
请注意:当索引超出范围时,Slice不会引发IndexError!
If the index is out of range, Python will try its best to set the index to 0
or len(s)
according to the situation. For example:
如果索引超出范围,巨蟒会根据情况尽量将索引设置为0或LEN(S)。例如:
s[:len(s)+5] # The same as s[:len(s)]
s[-len(s)-5::] # The same as s[0:]
s[len(s)+5::-1] # The same as s[len(s)::-1], and the same as s[::-1]
3. Examples
Let's finish this answer with examples, explaining everything we have discussed:
让我们用例子来结束这个回答,解释我们已经讨论过的一切:
# Create our array for demonstration
In [1]: s = [i for i in range(10)]
In [2]: s
Out[2]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [3]: s[2:] # From index 2 to last index
Out[3]: [2, 3, 4, 5, 6, 7, 8, 9]
In [4]: s[:8] # From index 0 up to index 8
Out[4]: [0, 1, 2, 3, 4, 5, 6, 7]
In [5]: s[4:7] # From index 4 (included) up to index 7(excluded)
Out[5]: [4, 5, 6]
In [6]: s[:-2] # Up to second last index (negative index)
Out[6]: [0, 1, 2, 3, 4, 5, 6, 7]
In [7]: s[-2:] # From second last index (negative index)
Out[7]: [8, 9]
In [8]: s[::-1] # From last to first in reverse order (negative step)
Out[8]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
In [9]: s[::-2] # All odd numbers in reversed order
Out[9]: [9, 7, 5, 3, 1]
In [11]: s[-2::-2] # All even numbers in reversed order
Out[11]: [8, 6, 4, 2, 0]
In [12]: s[3:15] # End is out of range, and Python will set it to len(s).
Out[12]: [3, 4, 5, 6, 7, 8, 9]
In [14]: s[5:1] # Start > end; return empty list
Out[14]: []
In [15]: s[11] # Access index 11 (greater than len(s)) will raise an IndexError
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-15-79ffc22473a3> in <module>()
----> 1 s[11]
IndexError: list index out of range
As a general rule, writing code with a lot of hardcoded index values leads to a readability
and maintenance mess. For example, if you come back to the code a year later, you’ll
look at it and wonder what you were thinking when you wrote it. The solution shown
is simply a way of more clearly stating what your code is actually doing.
In general, the built-in slice() creates a slice object that can be used anywhere a slice
is allowed. For example:
一般来说,使用大量硬编码索引值编写代码会导致可读性和维护混乱。例如,如果您在一年后返回到代码,您会看到它,并想知道当您编写它时您在想什么。显示的解决方案只是更清楚地说明代码实际在做什么的一种方式。通常,内置的Slice()创建一个切片对象,可以在任何允许切片的地方使用该对象。例如:
>>> items = [0, 1, 2, 3, 4, 5, 6]
>>> a = slice(2, 4)
>>> items[2:4]
[2, 3]
>>> items[a]
[2, 3]
>>> items[a] = [10,11]
>>> items
[0, 1, 10, 11, 4, 5, 6]
>>> del items[a]
>>> items
[0, 1, 4, 5, 6]
If you have a slice instance s, you can get more information about it by looking at its
s.start, s.stop, and s.step attributes, respectively. For example:
如果您有一个切片实例S,您可以通过分别查看它的s.start、s.Stop和s.Step属性来获取有关它的更多信息。例如:
>>> a = slice(10, 50, 2)
>>> a.start
10
>>> a.stop
50
>>> a.step
2
>>>
The previous answers don't discuss multi-dimensional array slicing which is possible using the famous NumPy package:
前面的答案没有讨论多维数组切片,这可以使用著名的NumPy包进行:
Slicing can also be applied to multi-dimensional arrays.
切片也可以应用于多维数组。
# Here, a is a NumPy array
>>> a
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
>>> a[:2, 0:3:2]
array([[1, 3],
[5, 7]])
The ":2
" before the comma operates on the first dimension and the "0:3:2
" after the comma operates on the second dimension.
逗号前的“:2”作用于第一维,逗号后的“0:3:2”作用于第二维。
The rules of slicing are as follows:
[lower bound : upper bound : step size]
I- Convert upper bound
and lower bound
into common signs.
I-将上界和下界转换为公共符号。
II- Then check if the step size
is a positive or a negative value.
然后检查步长是正值还是负值。
(i) If the step size
is a positive value, upper bound
should be greater than lower bound
, otherwise empty string
is printed. For example:
(I)如果步长为正值,则上界应大于下界,否则打印空串。例如:
s="Welcome"
s1=s[0:3:1]
print(s1)
The output:
输出:
Wel
However if we run the following code:
但是,如果我们运行以下代码:
s="Welcome"
s1=s[3:0:1]
print(s1)
It will return an empty string.
它将返回一个空字符串。
(ii) If the step size
if a negative value, upper bound
should be lesser than lower bound
, otherwise empty string
will be printed. For example:
(Ii)如果步长为负值,则上界应小于下界,否则将打印空字符串。例如:
s="Welcome"
s1=s[3:0:-1]
print(s1)
The output:
输出:
cle
But if we run the following code:
但如果我们运行以下代码:
s="Welcome"
s1=s[0:5:-1]
print(s1)
The output will be an empty string.
输出将是空字符串。
Thus in the code:
因此,在代码中:
str = 'abcd'
l = len(str)
str2 = str[l-1:0:-1] #str[3:0:-1]
print(str2)
str2 = str[l-1:-1:-1] #str[3:-1:-1]
print(str2)
In the first str2=str[l-1:0:-1]
, the upper bound
is lesser than the lower bound
, thus dcb
is printed.
在第一个str2=str[L-1:0:-1]中,上界小于下界,因此打印dcb。
However in str2=str[l-1:-1:-1]
, the upper bound
is not less than the lower bound
(upon converting lower bound
into negative value which is -1
: since index
of last element is -1 as well as 3).
然而,在str2=str[L-1:-1:-1]中,上界不小于下界(将下界转换为负值-1:因为最后一个元素的索引是-1和3)。
In my opinion, you will understand and memorize better the Python string slicing notation if you look at it the following way (read on).
在我看来,如果您按照下面的方式来看待它,您会更好地理解和记忆Python字符串切片表示法(继续阅读)。
Let's work with the following string ...
让我们使用以下字符串...
azString = "abcdefghijklmnopqrstuvwxyz"
For those who don't know, you can create any substring from azString
using the notation azString[x:y]
对于那些不知道的人,您可以使用符号azString[x:y]从azString创建任何子字符串
Coming from other programming languages, that's when the common sense gets compromised. What are x and y?
来自其他编程语言,这就是常识受到损害的时候。X和y是什么?
I had to sit down and run several scenarios in my quest for a memorization technique that will help me remember what x and y are and help me slice strings properly at the first attempt.
我不得不坐下来,运行了几个场景,寻找一种记忆技巧,帮助我记住x和y是什么,并帮助我在第一次尝试时正确地切分字符串。
My conclusion is that x and y should be seen as the boundary indexes that are surrounding the strings that we want to extra. So we should see the expression as azString[index1, index2]
or even more clearer as azString[index_of_first_character, index_after_the_last_character]
.
我的结论是,x和y应该被视为环绕我们想要额外添加的字符串的边界索引。因此,我们应该将该表达式看作azString[index1,index2],或者更清楚地将其看作azString[index_of_first_Character,index_After_the_last_Character]。
Here is an example visualization of that ...
这是一个可视化的例子。
Letters a b c d e f g h i j ...
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
┊ ┊
Indexes 0 1 2 3 4 5 6 7 8 9 ...
┊ ┊
cdefgh index1 index2
So all you have to do is setting index1 and index2 to the values that will surround the desired substring. For instance, to get the substring "cdefgh", you can use azString[2:8]
, because the index on the left side of "c" is 2 and the one on the right size of "h" is 8.
因此,您所要做的就是将index1和index2设置为所需的子字符串周围的值。例如,要获得子字符串“cdegh”,可以使用azString[2:8],因为“c”左边的索引是2,而“h”右边的索引是8。
Remember that we are setting the boundaries. And those boundaries are the positions where you could place some brackets that will be wrapped around the substring like this ...
请记住,我们正在设定边界。这些边界是您可以放置一些括号的位置,这些括号将像这样绕过子字符串。
a b [ c d e f g h ] i j
A b[c d e f g h]i j
That trick works all the time and is easy to memorize.
这个诀窍总是奏效,而且很容易记住。
I personally think about it like a for
loop:
我个人认为这是一个for循环:
a[start:end:step]
# for(i = start; i < end; i += step)
Also, note that negative values for start
and end
are relative to the end of the list and computed in the example above by given_index + a.shape[0]
.
另外,请注意,开始和结束的负值是相对于列表的结尾的,在上面的示例中,负值是通过给定的_index+a.shape[0]计算得出的。
#!/usr/bin/env python
def slicegraphical(s, lista):
if len(s) > 9:
print """Enter a string of maximum 9 characters,
so the printig would looki nice"""
return 0;
# print " ",
print ' '+'+---' * len(s) +'+'
print ' ',
for letter in s:
print '| {}'.format(letter),
print '|'
print " ",; print '+---' * len(s) +'+'
print " ",
for letter in range(len(s) +1):
print '{} '.format(letter),
print ""
for letter in range(-1*(len(s)), 0):
print ' {}'.format(letter),
print ''
print ''
for triada in lista:
if len(triada) == 3:
if triada[0]==None and triada[1] == None and triada[2] == None:
# 000
print s+'[ : : ]' +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] == None and triada[1] == None and triada[2] != None:
# 001
print s+'[ : :{0:2d} ]'.format(triada[2], '','') +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] == None and triada[1] != None and triada[2] == None:
# 010
print s+'[ :{0:2d} : ]'.format(triada[1]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] == None and triada[1] != None and triada[2] != None:
# 011
print s+'[ :{0:2d} :{1:2d} ]'.format(triada[1], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] != None and triada[1] == None and triada[2] == None:
# 100
print s+'[{0:2d} : : ]'.format(triada[0]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] != None and triada[1] == None and triada[2] != None:
# 101
print s+'[{0:2d} : :{1:2d} ]'.format(triada[0], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] != None and triada[1] != None and triada[2] == None:
# 110
print s+'[{0:2d} :{1:2d} : ]'.format(triada[0], triada[1]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] != None and triada[1] != None and triada[2] != None:
# 111
print s+'[{0:2d} :{1:2d} :{2:2d} ]'.format(triada[0], triada[1], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif len(triada) == 2:
if triada[0] == None and triada[1] == None:
# 00
print s+'[ : ] ' + ' = ', s[triada[0]:triada[1]]
elif triada[0] == None and triada[1] != None:
# 01
print s+'[ :{0:2d} ] '.format(triada[1]) + ' = ', s[triada[0]:triada[1]]
elif triada[0] != None and triada[1] == None:
# 10
print s+'[{0:2d} : ] '.format(triada[0]) + ' = ', s[triada[0]:triada[1]]
elif triada[0] != None and triada[1] != None:
# 11
print s+'[{0:2d} :{1:2d} ] '.format(triada[0],triada[1]) + ' = ', s[triada[0]:triada[1]]
elif len(triada) == 1:
print s+'[{0:2d} ] '.format(triada[0]) + ' = ', s[triada[0]]
if __name__ == '__main__':
# Change "s" to what ever string you like, make it 9 characters for
# better representation.
s = 'COMPUTERS'
# add to this list different lists to experement with indexes
# to represent ex. s[::], use s[None, None,None], otherwise you get an error
# for s[2:] use s[2:None]
lista = [[4,7],[2,5,2],[-5,1,-1],[4],[-4,-6,-1], [2,-3,1],[2,-3,-1], [None,None,-1],[-5,None],[-5,0,-1],[-5,None,-1],[-1,1,-2]]
slicegraphical(s, lista)
You can run this script and experiment with it, below is some samples that I got from the script.
您可以运行此脚本并对其进行试验,下面是我从脚本中获得的一些示例。
+---+---+---+---+---+---+---+---+---+
| C | O | M | P | U | T | E | R | S |
+---+---+---+---+---+---+---+---+---+
0 1 2 3 4 5 6 7 8 9
-9 -8 -7 -6 -5 -4 -3 -2 -1
COMPUTERS[ 4 : 7 ] = UTE
COMPUTERS[ 2 : 5 : 2 ] = MU
COMPUTERS[-5 : 1 :-1 ] = UPM
COMPUTERS[ 4 ] = U
COMPUTERS[-4 :-6 :-1 ] = TU
COMPUTERS[ 2 :-3 : 1 ] = MPUT
COMPUTERS[ 2 :-3 :-1 ] =
COMPUTERS[ : :-1 ] = SRETUPMOC
COMPUTERS[-5 : ] = UTERS
COMPUTERS[-5 : 0 :-1 ] = UPMO
COMPUTERS[-5 : :-1 ] = UPMOC
COMPUTERS[-1 : 1 :-2 ] = SEUM
[Finished in 0.9s]
When using a negative step, notice that the answer is shifted to the right by 1.
当使用负步时,请注意答案右移了1。
My brain seems happy to accept that lst[start:end]
contains the start
-th item. I might even say that it is a 'natural assumption'.
我的大脑似乎乐于接受第一个[开始:结束]包含开始项。我甚至可以说,这是一种‘自然假设’。
But occasionally a doubt creeps in and my brain asks for reassurance that it does not contain the end
-th element.
但偶尔会有一种怀疑潜入我的大脑,我的大脑要求保证它不包含结尾元素。
In these moments I rely on this simple theorem:
在这些时刻,我依赖于这个简单的定理:
for any n, lst = lst[:n] + lst[n:]
This pretty property tells me that lst[start:end]
does not contain the end
-th item because it is in lst[end:]
.
这个漂亮的属性告诉我,lst[Start:End]不包含End-th项,因为它在lst[end:]中。
Note that this theorem is true for any n
at all. For example, you can check that
请注意,这个定理对任何n都是成立的。例如,您可以检查
lst = range(10)
lst[:-42] + lst[-42:] == lst
returns True
.
返回True。
In Python, the most basic form for slicing is the following:
在Python中,切片的最基本形式如下所示:
l[start:end]
where l
is some collection, start
is an inclusive index, and end
is an exclusive index.
其中L是某个集合,START是包容性索引,END是独占性索引。
In [1]: l = list(range(10))
In [2]: l[:5] # First five elements
Out[2]: [0, 1, 2, 3, 4]
In [3]: l[-5:] # Last five elements
Out[3]: [5, 6, 7, 8, 9]
When slicing from the start, you can omit the zero index, and when slicing to the end, you can omit the final index since it is redundant, so do not be verbose:
从头开始切片时,可以省略零索引,切片到末尾时,可以省略最后一个索引,因为它是冗余的,所以不要冗长:
In [5]: l[:3] == l[0:3]
Out[5]: True
In [6]: l[7:] == l[7:len(l)]
Out[6]: True
Negative integers are useful when doing offsets relative to the end of a collection:
负整数在相对于集合末尾进行偏移时非常有用:
In [7]: l[:-1] # Include all elements but the last one
Out[7]: [0, 1, 2, 3, 4, 5, 6, 7, 8]
In [8]: l[-3:] # Take the last three elements
Out[8]: [7, 8, 9]
It is possible to provide indices that are out of bounds when slicing such as:
可以在切片时提供超出范围的索引,例如:
In [9]: l[:20] # 20 is out of index bounds, and l[20] will raise an IndexError exception
Out[9]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [11]: l[-20:] # -20 is out of index bounds, and l[-20] will raise an IndexError exception
Out[11]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Keep in mind that the result of slicing a collection is a whole new collection. In addition, when using slice notation in assignments, the length of the slice assignments do not need to be the same. The values before and after the assigned slice will be kept, and the collection will shrink or grow to contain the new values:
请记住,分割集合的结果是一个全新的集合。此外,在分配中使用切片表示法时,切片分配的长度不需要相同。分配的切片之前和之后的值将被保留,集合将缩小或增大以包含新值:
In [16]: l[2:6] = list('abc') # Assigning fewer elements than the ones contained in the sliced collection l[2:6]
In [17]: l
Out[17]: [0, 1, 'a', 'b', 'c', 6, 7, 8, 9]
In [18]: l[2:5] = list('hello') # Assigning more elements than the ones contained in the sliced collection l [2:5]
In [19]: l
Out[19]: [0, 1, 'h', 'e', 'l', 'l', 'o', 6, 7, 8, 9]
If you omit the start and end index, you will make a copy of the collection:
如果省略开始索引和结束索引,则将创建集合的副本:
In [14]: l_copy = l[:]
In [15]: l == l_copy and l is not l_copy
Out[15]: True
If the start and end indexes are omitted when performing an assignment operation, the entire content of the collection will be replaced with a copy of what is referenced:
如果在执行赋值操作时省略了起始索引和结束索引,则集合的整个内容将替换为引用的内容的副本:
In [20]: l[:] = list('hello...')
In [21]: l
Out[21]: ['h', 'e', 'l', 'l', 'o', '.', '.', '.']
Besides basic slicing, it is also possible to apply the following notation:
除基本切片外,还可以应用以下表示法:
l[start:end:step]
where l
is a collection, start
is an inclusive index, end
is an exclusive index, and step
is a stride that can be used to take every nth item in l
.
其中L是集合,Start是包容性索引,End是独占索引,Step是可以用来取L中每n项的步幅。
In [22]: l = list(range(10))
In [23]: l[::2] # Take the elements which indexes are even
Out[23]: [0, 2, 4, 6, 8]
In [24]: l[1::2] # Take the elements which indexes are odd
Out[24]: [1, 3, 5, 7, 9]
Using step
provides a useful trick to reverse a collection in Python:
使用STEP提供了一个有用的技巧来反转Python中的集合:
In [25]: l[::-1]
Out[25]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
It is also possible to use negative integers for step
as the following example:
也可以使用负整数作为步骤,如下例所示:
In[28]: l[::-2]
Out[28]: [9, 7, 5, 3, 1]
However, using a negative value for step
could become very confusing. Moreover, in order to be Pythonic, you should avoid using start
, end
, and step
in a single slice. In case this is required, consider doing this in two assignments (one to slice, and the other to stride).
但是,对步长使用负值可能会变得非常混乱。此外,为了成为Pythonic,你应该避免在一个切片中使用start、end和step。如果需要这样做,请考虑在两个赋值中执行此操作(一个是切片,另一个是步幅)。
In [29]: l = l[::2] # This step is for striding
In [30]: l
Out[30]: [0, 2, 4, 6, 8]
In [31]: l = l[1:-1] # This step is for slicing
In [32]: l
Out[32]: [2, 4, 6]
I want to add one Hello, World! example that explains the basics of slices for the very beginners. It helped me a lot.
我想添加一条Hello,World!这个例子为初学者解释了切片的基础知识。这对我帮助很大。
Let's have a list with six values ['P', 'Y', 'T', 'H', 'O', 'N']
:
让我们有一个包含六个值[‘P’,‘Y’,‘T’,‘H’,‘O’,‘N’的列表:
+---+---+---+---+---+---+
| P | Y | T | H | O | N |
+---+---+---+---+---+---+
0 1 2 3 4 5
Now the simplest slices of that list are its sublists. The notation is [<index>:<index>]
and the key is to read it like this:
现在,这个列表中最简单的部分就是它的子列表。符号是[
:
],关键是要这样读:
[ start cutting before this index : end cutting before this index ]
Now if you make a slice [2:5]
of the list above, this will happen:
现在,如果你对上面的列表做一个切片[2:5],就会发生这样的情况:
| |
+---+---|---+---+---|---+
| P | Y | T | H | O | N |
+---+---|---+---+---|---+
0 1 | 2 3 4 | 5
You made a cut before the element with index 2
and another cut before the element with index 5
. So the result will be a slice between those two cuts, a list ['T', 'H', 'O']
.
您在索引为2的元素之前进行了一个剪切,并在索引为5的元素之前进行了另一个剪切。因此,结果将是这两个剪切之间的一个切片,一个列表[‘T’,‘H’,‘O’]。
Most of the previous answers clears up questions about slice notation.
前面的大多数答案都澄清了有关切片表示法的问题。
The extended indexing syntax used for slicing is aList[start:stop:step]
, and basic examples are:
用于切片的扩展索引语法是ALL[START:STOP:STEP],基本示例如下:
:
:
More slicing examples: 15 Extended Slices
更多切片示例:15个扩展切片
The below is the example of an index of a string:
以下是字符串索引的示例:
+---+---+---+---+---+
| H | e | l | p | A |
+---+---+---+---+---+
0 1 2 3 4 5
-5 -4 -3 -2 -1
str="Name string"
Slicing example: [start:end:step]
切片示例:[Start:End:Step]
str[start:end] # Items start through end-1
str[start:] # Items start through the rest of the array
str[:end] # Items from the beginning through end-1
str[:] # A copy of the whole array
Below is the example usage:
以下是示例用法:
print str[0] = N
print str[0:2] = Na
print str[0:7] = Name st
print str[0:7:2] = Nm t
print str[0:-1:2] = Nm ti
I don't think that the Python tutorial diagram (cited in various other answers) is good as this suggestion works for positive stride, but does not for a negative stride.
我不认为Python教程图(在各种其他答案中引用)是好的,因为这个建议适用于正步幅,但不适用于负步幅。
This is the diagram:
这是一个图表:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
From the diagram, I expect a[-4,-6,-1]
to be yP
but it is ty
.
从图中,我预计[-4,-6,-1]是yp,但它是ty。
>>> a = "Python"
>>> a[2:4:1] # as expected
'th'
>>> a[-4:-6:-1] # off by 1
'ty'
What always work is to think in characters or slots and use indexing as a half-open interval -- right-open if positive stride, left-open if negative stride.
始终起作用的是在字符或槽中思考,并使用索引作为半开区间--如果是正步幅,则是右开步;如果是负步幅,则是左开步。
This way, I can think of a[-4:-6:-1]
as a(-6,-4]
in interval terminology.
这样,我就可以将[-4:-6:-1]看作区间术语中的(-6,-4)。
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5
-6 -5 -4 -3 -2 -1
+---+---+---+---+---+---+---+---+---+---+---+---+
| P | y | t | h | o | n | P | y | t | h | o | n |
+---+---+---+---+---+---+---+---+---+---+---+---+
-6 -5 -4 -3 -2 -1 0 1 2 3 4 5
If you feel negative indices in slicing is confusing, here's a very easy way to think about it: just replace the negative index with len - index
. So for example, replace -3 with len(list) - 3
.
如果您觉得切片中的负索引令人困惑,这里有一个非常简单的思考方法:只需将负索引替换为len-index。例如,将-3替换为len(List)-3。
The best way to illustrate what slicing does internally is just show it in code that implements this operation:
要在内部说明切片的作用,最好的方法就是在实现此操作的代码中显示它:
def slice(list, start = None, end = None, step = 1):
# Take care of missing start/end parameters
start = 0 if start is None else start
end = len(list) if end is None else end
# Take care of negative start/end parameters
start = len(list) + start if start < 0 else start
end = len(list) + end if end < 0 else end
# Now just execute a for-loop with start, end and step
return [list[i] for i in range(start, end, step)]
更多回答
Slicing builtin types returns a copy but that's not universal. Notably, slicing NumPy arrays returns a view that shares memory with the original.
对内置类型进行切片会返回一个副本,但这并不通用。值得注意的是,对NumPy数组进行切片会返回一个与原始数组共享内存的视图。
This is a beautiful answer with the votes to prove it, but it misses one thing: you can substitute None
for any of the empty spaces. For example [None:None]
makes a whole copy. This is useful when you need to specify the end of the range using a variable and need to include the last item.
这是一个美丽的答案,有选票证明了这一点,但它遗漏了一件事:你不能用任何空格来代替任何空格。例如,[None:None]会生成一个完整副本。当您需要使用变量指定范围的末尾并且需要包括最后一项时,这很有用。
Note that contrary to usual Python slices (see above), in Pandas Dataframes both the start and the stop are included when present in the index. For further info see the Pandas indexing documentation.
请注意,与通常的Python片(见上)相反,在Pandas Dataframe中,当索引中存在开始和结束时,都会包括开始和结束。有关更多信息,请参阅熊猫索引文档。
What really annoys me is that python says that when you don't set the start and the end, they default to 0 and the length of sequence. So, in theory, when you use "abcdef"[::-1] it should be transformed to "abcdef"[0:6:-1], but these two expressions does not get the same output. I feel that something is missing in python documentation since the creation of the language.
真正让我恼火的是,如果您不设置开始和结束,则它们默认为0和序列的长度。因此,从理论上讲,当您使用“ABCDEF”[::-1]时,它应该转换为“ABCDEF”[0:6:-1],但这两个表达式得到的输出并不相同。我觉得自从创建这种语言以来,在Python文档中就缺少了一些东西。
And I know that "abcdef"[::-1] is transformed to "abcdef"[6:-7:-1], so, the best way to explain would be: let len be the length of the sequence. If step is positive, the defaults for start and end are 0 and len. Else if step is negative, the defaults for start and end are len and -len - 1.
我知道“ABCDEF”[::-1]被转换为“ABCDEF”[6:-7:-1],所以,最好的解释方法是:让len是序列的长度。如果Step为正,则Start和End的默认值为0和len。否则,如果步骤为负,则开始和结束的缺省值为len和-len-1。
This suggestion works for positive stride, but does not for a negative stride. From the diagram, I expect a[-4,-6,-1]
to be yP
but it is ty
. What always work is to think in characters or slots and use indexing as a half-open interval -- right-open if positive stride, left-open if negative stride.
这个建议适用于积极的步伐,但不适用于消极的步伐。从图中,我预计[-4,-6,-1]是yp,但它是ty。始终起作用的是在字符或槽中思考,并使用索引作为半开区间--如果是正步幅,则是右开步;如果是负步幅,则是左开步。
But there's no way to collapse to an empty set starting from the end (like x[:0]
does when starting from the beginning), so you have to special-case small arrays. :/
但是没有办法从末尾开始折叠成一个空集(就像x[:0]从开头开始一样),所以你必须特殊情况下使用小数组。:/
@aguadopd You are absolutely right. The solution is to have the indices shifted to the right, centered just below the characters, and notice that the stop is always excluded. See another response just below.
@aguadopd你是完全正确的。解决方案是将索引向右移动,位于字符下方的中心,并注意停止总是被排除在外。下面是另一个答案。
Actually there is still something left out e.g. if I type 'apple'[4:-4:-1] I get 'elp', python is translating the -4 to a 1 maybe?
实际上还有一些遗漏的东西,例如,如果我输入‘Apple’[4:-4:-1],我得到‘elp’,而python正在将-4翻译成1呢?
note that backticks are deprecated in favour of repr
请注意,不建议使用反号,而应使用Repr
@liyuan The type implementing __getitem__
is; your example is equivalent to apple[slice(4, -4, -1)]
.
@梨园实现__getitem__的类型是;您的示例相当于Apple[Slice(4,-4,-1)]。
The first two tables are pure gold.
前两张桌子是纯金的。
If I wanted to remove the 1st x elements of a list, what will be better: l = l[6:]
or l[:] = l[6:]
?
如果我想删除列表的前x个元素,哪个更好:L=L[6:]还是L[:]=L[6:]?
The first way works for a list or a string; the second way only works for a list, because slice assignment isn't allowed for strings. Other than that I think the only difference is speed: it looks like it's a little faster the first way. Try it yourself with timeit.timeit() or preferably timeit.repeat(). They are super easy to use and very educational, it's worth getting used to playing with them all the time!
第一种方法适用于列表或字符串;第二种方法仅适用于列表,因为不允许对字符串进行切片分配。除此之外,我认为唯一的区别是速度:它看起来比第一种方式快一点。您可以使用timeit.timeit()亲自尝试,或者最好是使用timeit.Repeat()。它们非常容易使用,而且非常有教育意义,值得你习惯一直和它们一起玩!
Curious about what's the time complexity of doing r[1:1]=['blah']
? thanks!
想知道做r[1:1]=[‘废话’]的时间复杂度是多少?谢谢!
p[2:3] = 't' works fine ! there should be no TypeError !
P[2:3]=‘t’工作正常!不应该有类型错误!
@WinEunuuchs2Unix that's great feedback - this is a standard Python behavior, but it could be made clearer in that sort of way, so I'll consider updating my material to include this semantic.
@WinEunuuchs2Unix这是很好的反馈--这是一个标准的Python行为,但它可以通过这种方式变得更清楚,所以我会考虑更新我的材料,以包括这种语义。
Your answer is the only one (?) that touches the tip of what would be interesting here, when you write "slicable" - the rest is triviality. I wanted to know how the slicing is done, using the __getitem__
method. But if I understand well, you have to do all of it on your own: check whether the arg to your __getitem__
is an int or a slice (or what else could it be?), and in that (slice) case, deal with all possible cases ((A) or (A,B) or (A,B,C), and all possible sign combinations) on your own.... is that right?
你的答案是唯一的一个(?)当你写“Slicable”时,这就触及了这里有趣的地方--其余的都是琐碎的东西。我想知道切片是如何使用__getitem__方法完成的。但如果我理解得很好,你必须自己做所有的事情:检查你的__getitem_的参数是int还是Slice(或者它还可能是什么?),在那个Slice的情况下,自己处理所有可能的情况((A)或(A,B)或(A,B,C),以及所有可能的符号组合)。是那么回事吗?
another one interesting example: a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]; a[:-2:-2]
which results to [9]
另一个有趣的例子:A=[0,1,2,3,4,5,6,7,8,9];a[:-2:-2],结果是[9]
The this_is_how_slicing_works
is not the same as python slice. E.G. [0, 1, 2][-5:3:3]
will get [0] in python, but list(this_is_how_slicing_works([0, 1, 2], -5, 3, 3))
get [1].
This_is_How_SLICING_Works与Python切片不同。例如,[0,1,2][-5:3:3]将在python中获取[0],但list(This_is_How_Slicing_Works([0,1,2],-5,3,3))get[1]。
@Eastsun Oops, you're right! A clearer case: range(4)[-200:200:3] == [0, 3]
but list(this_is_how_slicing_works([0, 1, 2, 3], -200, 200, 3)) == [2]
. My if 0 <= i < len(seq):
was an attempt to implement "never go outside the sequence" simply but is wrong for step>1. I'll rewrite it later today (with tests).
@东方太阳哦,你说得对!一个更清楚的例子:Range(4)[-200:200:3]==[0,3]但List(This_is_How_SLICING_Works([0,1,2,3],-200,200,3))==[2]。My if 0<=i1是错误的。今天晚些时候我将重写它(使用测试)。
This is helpful; I had pondered why the ending index (in this case, Y of [X:Y]) was not included. i.e. Why [0:0] would not include the first index.
这很有帮助;我曾考虑过为什么不包括结束索引(在本例中是[X:Y]的Y)。即为什么[0:0]不包括第一个索引。
At last, I found here some explanation on why the slicing parameters start
and stop
and error-proof.
最后,我在这里找到了一些关于切片参数为什么启动和停止以及防错的解释。
Just a friendly reminder that you cannot do this on Python list
but only on array
in Numpy
只是一个友好的提醒,你不能在Python列表上这样做,而只能在Numpy中的数组上这样做
Used today 2021/07/19 by myself, qué capo aguadopd del pasado
今天2021/07/19我自己使用,魁卡波阿加德·德尔·帕萨多
As a newbie, this is an interesting way of thinking about it. However, the last example, counting from -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5 is a bit misleading because the string is NOT doubled like that. Furthermore, one can refer to the positive and negate positions like the following: a[-4:-6:-1] is the same as a[-4:0:-1] since the 0th position is the same as the -6th position. So I would just delete/ignore that example.
作为一名新手,这是一种有趣的思考方式。然而,最后一个例子,从-6,-5,-4,-3,-2,-1,0,1,2,3,4,5开始计数有点误导,因为字符串不是这样加倍的。此外,可以如下引用肯定和否定位置:A[-4:-6:-1]与A[-4:0:-1]相同,因为第0个位置与-6个位置相同。所以我只会删除/忽略这个例子。
我是一名优秀的程序员,十分优秀!