python:理解slice

我需要一个关于Python切片表示法的好解释(引用是一个加分项)。

对我来说,这个符号需要理解一下。

它看起来非常强大,但我还没有完全理解它。


其实很简单:

1
2
3
4
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

还有step值,它可以与上面任何一个值一起使用:

1
a[start:stop:step] # start through not past stop, by step

要记住的关键点是:stop值表示所选切片中没有的第一个值。因此,stopstart之间的区别是选择的元素数量(如果step为1,则为默认值)。

另一个特性是startstop可能是负数,这意味着它从数组的末尾而不是开头计数。所以:

1
2
3
a[-1]    # last item in the array
a[-2:]   # last two items in the array
a[:-2]   # everything except the last two items

同样,step可以是负数:

1
2
3
4
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对程序员很友好。例如,如果您要求a[:-2]a只包含一个元素,您将得到一个空列表,而不是一个错误。有时您希望出现错误,因此您必须意识到可能会发生这种情况。

关系到slice()对象

切片操作符[]实际上在上述代码中与使用:表示法的slice()对象一起使用(该表示法仅在[]中有效),即:

1
a[start:stop:step]

等价于:

1
a[slice(start, stop, step)]

根据参数的数量,Slice对象的行为也略有不同,类似于range(),即同时支持slice(stop)slice(start, stop[, step])。要跳过指定给定的参数,可以使用None,例如a[start:]等价于a[slice(start, None)]a[::-1]等价于a[slice(None, None, -1)]

虽然基于:的表示法对于简单的切片非常有用,但是显式使用slice()对象简化了切片的编程生成。


Python教程对此进行了讨论(向下滚动一点,直到看到关于切片的部分)。

ASCII艺术图表也有助于记住切片是如何工作的:

1
2
3
4
5
 +---+---+---+---+---+---+
 | 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.


列举文法容许的可能性:

1
2
3
4
5
6
7
8
>>> seq[:]                # [seq[0],   seq[1],          ..., seq[-1]    ]
>>> seq[low:]             # [seq[low], seq[low+1],      ..., seq[-1]    ]
>>> seq[:high]            # [seq[0],   seq[1],          ..., seq[high-1]]
>>> seq[low:high]         # [seq[low], seq[low+1],      ..., seq[high-1]]
>>> seq[::stride]         # [seq[0],   seq[stride],     ..., seq[-1]    ]
>>> seq[low::stride]      # [seq[low], seq[low+stride], ..., seq[-1]    ]
>>> seq[:high:stride]     # [seq[0],   seq[stride],     ..., seq[high-1]]
>>> seq[low:high:stride]  # [seq[low], seq[low+stride], ..., seq[high-1]]

当然,如果(high-low)%stride != 0,那么端点将比high-1略低。

如果stride是负数,那么顺序会发生一些变化,因为我们在倒数:

1
2
3
4
>>> seq[::-stride]        # [seq[-1],   seq[-1-stride],   ..., seq[0]    ]
>>> seq[high::-stride]    # [seq[high], seq[high-stride], ..., seq[0]    ]
>>> seq[:low:-stride]     # [seq[-1],   seq[-1-stride],   ..., seq[low+1]]
>>> seq[high:low:-stride] # [seq[high], seq[high-stride], ..., seq[low+1]]

扩展切片(使用逗号和省略号)主要只用于特殊的数据结构(如NumPy);基本序列不支持它们。

1
2
3
4
5
6
>>> class slicee:
...     def __getitem__(self, item):
...         return `item`
...
>>> slicee()[0, 1:2, ::5, ...]
'(0, slice(1, 2, None), slice(None, None, 5), Ellipsis)'


上面的答案没有讨论切片分配。为了理解片分配,在ASCII艺术中添加另一个概念是有帮助的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
                +---+---+---+---+---+---+
                | 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']

一个启发式是,对于从0到n的切片,可以这样想:"0是开始,从开始处开始,取列表中的n个项"。

1
2
3
4
5
6
>>> 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']

另一种启发式是,"对于任何切片,将开始部分替换为0,应用前面的启发式得到列表的末尾,然后重新计算第一个数字,将开始部分删除。"

1
2
3
4
5
6
7
>>> 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.

切片分配的第一条规则是,由于切片返回一个列表,切片分配需要一个列表(或其他可迭代的):

1
2
3
4
5
6
7
8
9
>>> 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

切片赋值的第二条规则,你也可以在上面看到,就是无论切片索引返回列表的哪一部分,切片赋值所改变的部分都是相同的:

1
2
3
4
5
>>> p[2:4]
 ['T','h']
>>> p[2:4] = ['t','r']
>>> p
 ['P','y','t','r','o','n']

切片赋值的第三条规则是,赋值列表(iterable)不必具有相同的长度;索引切片被简单地切掉,然后被分配给它的东西全部替换掉:

1
2
3
4
>>> 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']

最难适应的部分是分配给空片。使用启发式1和启发式2很容易让你的脑袋转到索引一个空切片:

1
2
3
4
5
6
7
8
9
10
11
>>> 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]
 []

一旦你看到了,切片分配给空切片也是有意义的:

1
2
3
4
5
6
7
8
9
10
11
12
>>> 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

注意,由于我们没有更改片的第二个数字(4),插入的项总是与"o"相对,即使是在分配空片时也是如此。因此,空片赋值的位置是非空片赋值位置的逻辑扩展。

倒回去一点,当你继续我们开始计算切片的时候会发生什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>> 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]
 []

通过切片,一旦你完成了,你就完成了;它不会开始向后切片。在Python中,除非使用负数显式地请求它们,否则不会得到负的步长。

1
2
>>> p[5:3:-1]
 ['n','o']

有一些奇怪的后果"一旦你做了,你做的"规则:

1
2
3
4
5
6
7
8
9
10
>>> 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

事实上,与索引相比,Python切片具有奇怪的防错性:

1
2
3
4
>>> p[100:200]
 []
>>> p[int(2e99):int(1e99)]
 []

这有时很有用,但也会导致一些奇怪的行为:

1
2
3
4
5
>>> 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']

根据你的申请,这可能……也可能不会…正如你所希望的那样!

<人力资源/ >

下面是我最初的答案。它对很多人都很有用,所以我不想删除它。

1
2
3
4
5
6
7
8
9
>>> 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]

这也可能阐明切片和索引之间的区别。


Explain Python's slice notation

简而言之,下标表示法(subscriptable[subscriptarg])中的冒号(:)构成切片表示法——其中有可选参数startstopstep:

1
sliceable[start:stop:step]

Python切片是一种计算速度快的方法,可以有条不紊地访问数据的一部分。在我看来,即使是一个中级Python程序员,也需要熟悉Python语言的一个方面。

重要定义

首先,让我们定义几个术语:

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.

索引是如何工作的

你可以取这些正数或负数中的任何一个。正数的含义很简单,但是对于负数,就像Python中的索引一样,从末尾开始和结束向后计数,对于步骤,只需减少索引。这个例子来自于文档的教程,但是我稍微修改了一下,以指示每个索引引用序列中的哪个项:

1
2
3
4
5
 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
   0   1   2   3   4   5
  -6  -5  -4  -3  -2  -1

切片是如何工作的

要对支持它的序列使用切片表示法,必须在序列后面的方括号中包含至少一个冒号(根据Python数据模型,它实际上实现了序列的__getitem__方法)。

切片表示法是这样工作的:

1
sequence[start:stop:step]

记住,start、stop和step都有默认值,因此要访问默认值,只需忽略参数。

切片表示法从列表(或任何其他支持它的序列,如字符串)中获取最后九个元素,如下所示:

1
my_list[-9:]

当我看到这个的时候,我把括号里的部分读成"9从末尾到末尾"。(实际上,我在心里把它缩写为"-9,on")

解释:

完整的符号是

1
my_list[-9:None:None]

替换默认值(实际上,当step为负数时,stop的默认值为-len(my_list) - 1,因此None for stop实际上只是意味着它走到它要走的任何结束步骤):

1
my_list[-9:len(my_list):1]

冒号:告诉Python您要给它一个切片,而不是一个常规索引。这就是为什么在python2中创建列表浅拷贝的惯用方法是

1
list_copy = sequence[:]

清除它们的方法是:

1
del my_list[:]

(Python 3获得一个list.copylist.clear方法。)

step为负数时,startstop的缺省值更改为

默认情况下,当step参数为空(或None)时,它被分配给+1

但是您可以传入一个负整数,列表(或大多数其他标准切片)将从末尾被切片到开头。

因此,一个负片将更改startstop的默认值!

在源文件中证实了这一点

我希望鼓励用户阅读源代码和文档。切片对象的源代码和这个逻辑可以在这里找到。首先我们确定step是否为负数:

1
 step_is_negative = step_sign < 0;

如果是这样,下界是-1,这意味着我们一直切片到并包括开始,上界是长度- 1,这意味着我们从结束开始。(注意,这个-1的语义不同于一个-1,用户可以用Python传递指示最后一项的索引。)

1
2
3
4
5
6
7
8
9
if (step_is_negative) {
    lower = PyLong_FromLong(-1L);
    if (lower == NULL)
        goto error;

    upper = PyNumber_Add(length, lower);
    if (upper == NULL)
        goto error;
}

否则step为正,下界为零,上界(我们向上移动,但不包括)为切片列表的长度。

1
2
3
4
5
6
else {
    lower = _PyLong_Zero;
    Py_INCREF(lower);
    upper = length;
    Py_INCREF(upper);
}

然后,我们可能需要为startstop应用默认值——当step为负数时,则为start的默认值计算为上界:

1
2
3
4
if (self->start == Py_None) {
    start = step_is_negative ? upper : lower;
    Py_INCREF(start);
}

stop,下界:

1
2
3
4
if (self->stop == Py_None) {
    stop = step_is_negative ? lower : upper;
    Py_INCREF(stop);
}

给你的切片一个描述性的名字

您可能会发现将形成切片与将其传递给list.__getitem__方法分开是很有用的(这就是方括号的作用)。即使您对它并不陌生,它也可以使您的代码更具可读性,以便其他可能需要阅读您的代码的人能够更容易地理解您在做什么。

然而,您不能仅仅将一些用冒号分隔的整数分配给变量。你需要使用切片对象:

1
last_nine_slice = slice(-9, None)

第二个参数None是必需的,因此第一个参数被解释为start参数,否则就是stop参数。

然后你可以将切片对象传递给你的序列:

1
2
>>> list(range(100))[last_nine_slice]
[91, 92, 93, 94, 95, 96, 97, 98, 99]

有趣的是,范围也可以切片:

1
2
>>> range(100)[last_nine_slice]
range(91, 100)

内存注意事项:

由于Python列表的切片在内存中创建新对象,另一个需要注意的重要函数是itertools.islice。通常,您希望在片上进行迭代,而不只是在内存中静态地创建它。islice非常适合这个。需要注意的是,它不支持对startstopstep的负参数,因此如果这是一个问题,您可能需要提前计算索引或反转迭代器。

1
2
3
length = 100
last_nine_iter = itertools.islice(list(range(length)), length-9, None, 1)
list_last_nine = list(last_nine_iter)

现在:

1
2
>>> list_last_nine
[91, 92, 93, 94, 95, 96, 97, 98, 99]

列表切片复制的事实是列表本身的一个特性。如果要分割像panda DataFrame这样的高级对象,它可能会返回原始视图,而不是副本。


当我第一次看到切分语法时,有几件事我并没有马上意识到:

1
2
3
>>> x = [1,2,3,4,5,6]
>>> x[::-1]
[6,5,4,3,2,1]

反转序列的简单方法!

如果你想,出于某种原因,每第二项的顺序颠倒一下:

1
2
3
>>> x = [1,2,3,4,5,6]
>>> x[::-2]
[6,4,2]

在Python 2.7

切片在Python中

1
2
3
4
5
6
7
8
9
[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).

理解索引分配是非常重要的。

1
2
3
In forward direction, starts at 0 and ends at len-1

In backward direction, starts at -1 and ends at -len

当您说[a:b:c]时,您是说根据c的符号(向前或向后),从a开始到b结束(不包括bth索引处的元素)。使用上面的索引规则,记住你只能找到这个范围内的元素:

1
-len, -len+1, -len+2, ..., 0, 1, 2,3,4 , len -1

但这个范围在两个方向上无限延伸:

1
...,-len -2 ,-len-1,-len, -len+1, -len+2, ..., 0, 1, 2,3,4 , len -1, len, len +1, len+2 , ....

例如:

1
2
3
             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

如果您选择的a、b和c允许在使用上面的a、b、c规则进行遍历时与上面的范围重叠,那么您要么得到一个包含元素的列表(遍历过程中接触到),要么得到一个空列表。

最后一件事:如果a和b相等,那么你也会得到一个空列表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
>>> 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]


在http://wiki.python.org/moin/movingtopythonfrommotherlanguages上找到了这个很棒的表

1
2
3
4
5
6
7
8
9
10
11
12
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)

在使用它之后,我意识到最简单的描述是它与for循环中的参数完全相同……

1
(from:to:step)

其中任何一个都是可选的:

1
2
3
(:to:step)
(from::step)
(from:to)

然后负索引只需要把字符串的长度加到负索引上就可以理解了。

不管怎样,这对我很有用……


我发现更容易记住它是如何工作的,然后我就可以计算出任何特定的开始/停止/步骤组合。

首先理解range()是有指导意义的:

1
2
3
4
5
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

start开始,按step递增,不达到stop。非常简单。

关于负步骤要记住的是,stop总是被排除在外的端,无论它是高还是低。如果您想要以相反的顺序进行相同的切片,那么单独执行反转要干净得多:例如'abcde'[1:-2][::-1]从左边切片一个字符,从右边切片两个字符,然后反转。(参见reversed())。

序列切片是一样的,只是它首先对负索引进行归一化,并且永远不能超出序列:

TODO:当abs(step)>1时,下面的代码有一个bug,"永远不要超出序列";我想我把它打对了,但是很难理解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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]

不要担心is None的细节—只要记住省略start和/或stop总是能够正确地给出整个序列。

正态化负索引首先允许从末尾独立地计算start和/或stop: 'abcde'[1:-2] == 'abcde'[1:3] == 'bc'不管range(1,-2) == []。规范化有时被认为是"长度的模",但是注意,它只添加一次长度:例如'abcde'[-53:42]只是整个字符串。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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   :
|--------------->
    <---------------|

我希望这将有助于您用Python对列表进行建模。

参考:http://wiki.python.org/moin/MovingToPythonFromOtherLanguages


我使用"元素间的索引点"方法来思考它,但是描述它的一种方法是这样的:

1
mylist[X:Y]

X是你想要的第一个元素的下标。Y是你不想要的第一个元素的下标。


Python切片符号:

1
a[start:end:step]

对于startend,负值被解释为相对于序列的末尾。end的正指数表示要包含的最后一个元素之后的位置。空值的默认值如下:[+0:-0:1]。使用负步骤将反转startend的解释

符号扩展到(numpy)矩阵和多维数组。例如,要分割整个列,可以使用:

1
m[::,0:2:] ## slice the first two columns

片包含数组元素的引用,而不是副本。如果想单独复制一个数组,可以使用deepcopy()


我是这样教新手切片的:

理解索引和切片之间的区别:

Wiki Python有这张令人惊奇的图片,它清楚地区分了索引和切片。

enter image description here

它是一个包含6个元素的列表。为了更好地理解切片,可以将该列表视为一组六个框放在一起的列表。每个盒子里都有一个字母表。

索引就像处理方框的内容。您可以检查任何框的内容。但你不能同时检查多个框的内容。您甚至可以替换框中的内容。但是你不能把两个球放在一个盒子里或者一次换两个球。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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

切片就像处理盒子本身。你可以拿起第一个盒子放在另一张桌子上。要拿起箱子,你所需要知道的只是开始和开始的位置。盒子的末端。

您甚至可以取前3箱或后2箱,或1箱与1箱之间的所有箱。4. 所以,你可以选择任何一组盒子,如果你知道开始和结束;的结局。这个职位叫做start &停止的位置。

有趣的是,您可以同时替换多个框。你也可以把多个盒子放在任何你喜欢的地方。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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']

切片与步骤:

直到现在你还在不停地捡箱子。但有些时候你需要谨慎地挑选。例如,你可以每隔一秒拿一个盒子。你甚至可以每隔三分之一的盒子从最后拿起。这个值称为步长。这表示连续拾取的间隔。如果你从头到尾挑选盒子,那么步长应该是正的,反之亦然。

1
2
3
4
5
6
7
8
9
10
11
12
13
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]: []

Python如何找出缺失的参数:

在切片时,如果省略了任何参数,Python会自动计算出来。

如果您检查CPython的源代码,您将发现一个名为PySlice_GetIndicesEx的函数,它为任何给定参数计算一个切片的索引。下面是Python中的逻辑等价代码。

这个函数接受一个Python对象&可选参数切片和返回开始,停止,步骤和放大器;请求切片的切片长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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)

这就是切片背后的智能。由于Python内建了一个名为slice的函数,所以可以传递一些参数。检查它计算缺失参数的能力。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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]

注:这篇文章最初写在我的博客http://www.avilpage.com/2015/03/a- piece of pythonintelligens-behind.html


这只是一些额外的信息…考虑下面的列表

1
>>> l=[12,23,345,456,67,7,945,467]

扭转这一趋势的其他技巧很少:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> 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]

参见上面abc的回答


您还可以使用切片分配来删除列表中的一个或多个元素:

1
2
3
4
r = [1, 'blah', 9, 8, 2, 3, 4]
>>> r[1:4] = []
>>> r
[1, 2, 3, 4]


一般来说,编写带有大量硬编码索引值的代码会提高可读性和维护混乱。例如,如果您在一年后再回到代码,您将会看着它,想想你写它的时候在想什么。所示的解决方案只是一种更清楚地说明代码实际在做什么的方法。通常,内置的slice()创建一个slice对象,该对象可以在片的任何地方使用是被允许的。例如:

1
2
3
4
5
6
7
8
9
10
11
12
>>> 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]

如果您有一个slice实例s,您可以通过查看它来获得关于它的更多信息年代。首先,s。停止和年代。一步属性,分别。例如:

1
2
3
4
5
6
7
8
>>> a = slice(10, 50, 2)
>>> a.start
10
>>> a.stop
50
>>> a.step
2
>>>

1。片符号

使它简单,记得片只有一种形式:

1
s[start:end:step]

它是这样工作的:

s:一个可以切片的对象start:开始迭代的第一个索引end:最后一个索引,注意end索引不会包含在结果切片中step:选择每个step索引的元素

另一个重要的东西:所有startendstep都可以省略!如果省略它们,则使用它们的默认值:0len(s)1

所以可能的变化是:

1
2
3
4
5
6
7
8
9
10
11
12
# 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[:]

注意:如果start>=end(只考虑当step>0), python将返回一个空切片[]

2。陷阱

上面的部分解释了slice工作原理的核心特性,它在大多数情况下都会工作。然而,也可能会有一些陷阱,您应该小心,本部分将对此进行解释。

负索引

首先让python学习者感到困惑的是索引可以是负数!不要惊慌:负指数的意思是向后计数。

例如:

1
2
3
4
s[-5:]    # start at the 5th index from the end of array,
          # thus returns the last 5 elements
s[:-5]    # start at index 0, end until the 5th index from end of array,
          # thus returns s[0:len(s)-5]

-

更令人困惑的是step也可以是负数!

负步骤意味着向后迭代数组:从结束到开始,包含结束索引,并从结果中排除开始索引。

注意:当step为负数时,startlen(s)的默认值(而end不等于0,因为s[::-1]包含s[0])。例如:

1
2
3
s[::-1]            # reversed slice
s[len(s)::-1]      # same as above, reversed slice
s[0:len(s):-1]     # empty list

超出范围错误?

吃惊:当指数超出范围时切片不提高硬度!

如果索引超出范围,python会根据情况将索引设置为0len(s)。例如:

1
2
3
s[:len(s)+5]      # same as s[:len(s)]
s[-len(s)-5::]    # same as s[0:]
s[len(s)+5::-1]   # same as s[len(s)::-1], same as s[::-1]

3。示例

让我们用例子来结束这个答案,解释我们讨论过的所有问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 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, 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 IndexError
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-15-79ffc22473a3> in <module>()
----> 1 s[11]

IndexError: list index out of range


以上答案不讨论多维数组切片,这是可能使用著名的numpy包:

切片也适用于多维数组。

1
2
3
4
5
6
7
8
9
# 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]])

逗号前的":2"作用于第一个维度,逗号后的"0:3:2"作用于第二个维度。


我的大脑似乎乐于接受lst[start:end]包含start-th项。我甚至可以说这是一个"自然的假设"。

但偶尔也会有疑问,我的大脑会要求我保证它不包含end-th元素。

在这些时刻,我依靠这个简单的定理:

1
for any n,    lst = lst[:n] + lst[n:]

这个漂亮的属性告诉我lst[start:end]不包含end-th项,因为它在lst[end:]中。

注意,这个定理对任何n都是成立的。例如,你可以检查一下

1
2
lst = range(10)
lst[:-42] + lst[-42:] == lst

返回True


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#!/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)

您可以运行这个脚本并使用它进行实验,下面是我从脚本中获得的一些示例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  +---+---+---+---+---+---+---+---+---+
  | 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]

当使用负步骤时,注意答案向右移动了1。


在Python中,最基本的切片形式如下:

l[start:end]

其中l是某个集合,start是一个包含索引,end是一个排他索引。

1
2
3
4
5
6
7
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]

从开始切片时,可以省略zero索引;从切片到结束时,可以省略final索引,因为它是冗余的,所以不要太冗长:

1
2
3
4
5
In [5]: l[:3] == l[0:3]
Out[5]: True

In [6]: l[7:] == l[7:len(l)]
Out[6]: True

当执行相对于集合末尾的偏移时,负整数很有用:

1
2
3
4
5
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 3 elements
Out[8]: [7, 8, 9]

可以在切片时提供超出边界的索引,例如:

1
2
3
4
5
In [9]: l[:20] # 20 is out of index bounds, 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, l[-20] will raise an IndexError exception
Out[11]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

请记住,分割一个集合的结果是一个全新的集合。此外,当在赋值中使用片符号时,片赋值的长度不需要相同。将保留分配切片前后的值,集合将收缩或增长以包含新值:

1
2
3
4
5
6
7
8
9
In [16]: l[2:6] = list('abc') # assigning less 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]

如果你省略了开始和结束索引,你会复制集合:

1
2
3
4
In [14]: l_copy = l[:]

In [15]: l == l_copy and l is not l_copy
Out[15]: True

如果在执行赋值操作时省略开始和结束索引,则集合的全部内容将替换为引用内容的副本:

1
2
3
4
In [20]: l[:] = list('hello...')

In [21]: l
Out[21]: ['h', 'e', 'l', 'l', 'o', '.', '.', '.']

除了基本的切片,还可以应用以下符号:

1
l[start:end:step]

其中l是一个集合,start是一个包含索引,end是一个排他索引,step是一个步骤,可用于处理l中的每一个第n项。

1
2
3
4
5
6
7
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]

使用step提供了一个有用的技巧来反转Python中的集合:

1
2
In [25]: l[::-1]
Out[25]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

也可以对step使用负整数,例如:

1
2
In[28]:  l[::-2]
Out[28]: [9, 7, 5, 3, 1]

然而,为step使用负值可能会变得非常混乱。此外,为了符合python的要求,应该避免在单个片中使用startendstep。如果需要这样做,可以考虑在两个任务中完成(一个任务是切片,另一个任务是大步前进)。

1
2
3
4
5
6
7
8
9
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]

上面的大部分答案都澄清了切片表示法。用于切片的扩展索引语法是aList[start:stop:step]基本的例子是

enter image description here:

更多的切片示例:15个扩展切片


下面是字符串索引的例子

1
2
3
4
5
6
7
 +---+---+---+---+---+
 | H | e | l | p | A |
 +---+---+---+---+---+
 0   1   2   3   4   5
-5  -4  -3  -2  -1

str="Name string"

切片的例子:[开始:结束步骤):

1
2
3
4
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

下面是示例用法

1
2
3
4
5
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


我想添加一个Hello world示例,为非常初学者解释切片的基础知识。它帮了我很多。

让我们有一个包含6个值的列表['P', 'Y', 'T', 'H', 'O', 'N']:

1
2
3
4
+---+---+---+---+---+---+
| P | Y | T | H | O | N |
+---+---+---+---+---+---+
  0   1   2   3   4   5

这个列表中最简单的部分是它的子列表。符号是[:],关键是这样读:

1
[ start cutting before this index : end cutting before this index ]

现在如果你对上面的列表进行切片[2:5],将会发生以下情况:

1
2
3
4
5
        |           |
+---+---|---+---+---|---+
| P | Y | T | H | O | N |
+---+---|---+---+---|---+
  0   1 | 2   3   4 | 5

您在索引为2的元素前进行了一次切割,然后在索引为5的元素前进行了另一次切割。因此结果将是这两个切分之间的一个切分,一个列表['T', 'H', 'O']


呵呵呵,看到自己在2600多人投票后试图给出一个更好更简单的解释,这有点奇怪。

我们开始…

在我看来,如果您按照以下方式查看Python字符串切片表示法,您将更好地理解和记忆它。

让我们用下面的字符串…

1
azString ="abcdefghijklmnopqrstuvwxyz"

对于不知道的人,可以使用azString[x:y]符号从azString创建任何子字符串

来自其他编程语言,这是常识受到损害的时候。x和y是什么?

我不得不坐下来,运行几个场景来寻求一种记忆技巧,它将帮助我记住x和y是什么,并在第一次尝试时帮助我正确地分割字符串。

我的结论是,x和y应该被看作是围绕我们想要添加的字符串的边界索引。因此,我们应该看到表达式为azString[index1, index2],或者更清晰地为azString[index_of_first_character, index_after_the_last_character]

这里有一个可视化的例子。


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

因此,如果要将index1和index2设置为将包围所需子字符串的值,则只需执行以下操作。例如,要获得子字符串"cdefgh",可以使用azString[2:8],因为"c"左边的索引是2,而"h"右边的索引是8。

记住,我们是在设定界限。

这个技巧一直都很有效,而且很容易记住。

希望这能有所帮助。


如果您觉得切片中的负索引令人困惑,这里有一个非常简单的方法来考虑:用len - index替换负索引。例如,用len(list) - 3替换-3。

最好的方法来说明切片在内部做什么,只是显示它在代码中实现这个操作:

1
2
3
4
5
6
7
8
9
10
11
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 for-loop with start, end and step
  return [list[i] for i in range(start, end, step)]

切片:-蛇出现在你的脚附近。它从无形变为有形。我们的视野只显示了世界的一部分。类似地,Python切片根据开始和停止提取元素。我们在Python中对许多类型进行切片。我们指定一个可选的第一个索引、一个可选的最后一个索引和一个可选步骤。

1
2
3
4
5
values[1:3]  Index 1 through index 3.
values[2:-1] Index 2 through index one from last.
values[:2]   Start through index 2.
values[2:]   Index 2 through end.
values[::2]  Start through end, skipping ahead 2 places each time.

你可以得到很好的例子在下面的链接:-python切片表示法示例


基本的切片技术是定义起始点、停止点和步长(也称为步长)。

首先,我们将创建一个值列表,用于切片。

创建两个要切片的列表,第一个是从1到9的数字列表(列表a)。第二个也是一个数字列表,从0到9(列表B)

1
2
3
4
5
A = list(range(1,10,1)) # start,stop,step
B = list(range(9))

print("This is List A:",A)
print("This is List B:",B)

索引A中的3和B中的6。

1
2
print(A[2])
print(B[6])

基本的切片

用于切片的扩展索引语法是aList[start:stop:step]。start参数和step参数都默认为none—惟一需要的参数是stop。您是否注意到这类似于使用range来定义列表A和B?这是因为slice对象表示range(start、stop、step)指定的一组索引。Python 3.4的文档

可以看到,只定义stop返回一个元素。由于start默认为none,这意味着只检索一个元素。

需要注意的是,第一个元素是索引0,而不是索引1。这就是为什么我们在这个练习中使用两个列表。列表A的元素根据序号位置进行编号(第一个元素是1,第二个元素是2,等等),而列表B的元素是用来索引它们的数字(第一个元素0的[0],等等)。

使用扩展索引语法,我们检索一系列值。例如,所有值都用冒号检索。

1
A[:]

要检索元素的子集,需要定义开始和停止位置。

给定pattern aList[start:stop],从列表A检索前两个元素


如果我们能将切片与range关联起来,就很容易理解了,range给出了索引。我们可以将切片分为以下两类:

1。没有步骤或步骤> 0。例如,[i:j][i:j:k] (k>0)

假设序列是s=[1,2,3,4,5]

如果00,则[i:j:k] -> range(i,j,k)

例如,[0:3:2] -> range(0,3,2) -> 0, 2

如果i>len(s)j>len(s),则i=len(s)j=len(s)

例如,[0:100:2] -> range(0,len(s),2) -> range(0,5,2) -> 0, 2, 4

如果i<0j<0,则i=max(0,len(s)+i)j=max(0,len(s)+j)

例如,[0:-3:2] -> range(0,len(s)-3,2) -> range(0,2,2) -> 0

另一个例子是[0:-1:2] -> range(0,len(s)-1,2) -> range(0,4,2) -> 0, 2

如果没有指定i,则i=0

例如,[:4:2] -> range(0,4,2) -> range(0,4,2) -> 0, 2

如果没有指定j,则j=len(s)

例如,[0::2] -> range(0,len(s),2) -> range(0,5,2) -> 0, 2, 4

2。< 0。例如,[i:j:k] (k<0)

假设序列是s=[1,2,3,4,5]

如果00,则[i:j:k] -> range(i,j,k)

例如,[5:0:-2] -> range(5,0,-2) -> 5, 3, 1

如果i>len(s)j>len(s),则i=len(s)-1j=len(s)-1

例如,[100:0:-2] -> range(len(s)-1,0,-2) -> range(4,0,-2) -> 4, 2

如果i<0j<0,则i=max(-1,len(s)+i)j=max(-1,len(s)+j)

例如,[-2:-10:-2] -> range(len(s)-2,-1,-2) -> range(3,-1,-2) -> 3, 1

如果没有指定i,则i=len(s)-1

例如,[:0:-2] -> range(len(s)-1,0,-2) -> range(4,0,-2) -> 4, 2

如果没有指定j,则j=-1

例如,[2::-2] -> range(2,-1,-2) -> 2, 0

另一个例子是[::-1] -> range(len(s)-1,-1,-1) -> range(4,-1,-1) -> 4, 3, 2, 1, 0

总之

enter image description here


上面的每个人都解释得很好。我想给它加上一个简单的解释。As:是一个切片操作符,它排除后面提到的数组索引(:),包括前面提到的数组索引(:)。例如

[included array indices starting index:excluded array starting index]

a[-1] # last item in the array (included)

a[-2:] # only last two items in the array (included)

a[:-2] # everything except the last two items(excluded)

a[:] # all the items in the array are included