Python切片操作的一些问题

(不写点什么的话显示出来是全文)

今天看到个有意思的问题:
有以下代码片段,问输出是什么。

1
2
a = ['1', '2', '3', '4', '5']
print(a[:5])

试了下输出是['1', '2', '3', '4', '5']
很明显索引值越界了,但是这里有个切片操作导致有输出结果而不报错。然后又试了下print(a[5:])

1
2
a = ['1', '2', '3', '4', '5']
print(a[5:])

输出是[]
上网查了下找到了“Python 序列的切片操作与技巧”这篇博文的一个解释,不过仍有些难以说清的问题:
切片的方法是consequence[start_index: stop_index: step]
start_index默认为0或者-len(consequence)
stop_index默认为len(consequence)-1或者-1。
step默认为1。
其中切片结果包含索引值为start_index的对象但不包含索引值为stop_index的对象。
当输入的索引值超出[-len(consequence), len(consequence)-1]这个区间时会被置为相应的缺省值。但是按照这个解释,a[:5]会被缺省为a[:len(consequence)-1],输出应该是['1', '2', '3', '4']。另外按照个缺省值的说法,a[:]会被缺省为a[0:len(consequence)-1]与实际的结果也不符。同样的,上述解释也无法说明a[5:]的结果为空的原因。
按照“全面深入彻底理解Python切片操作”这篇博文所说的,切片操作中存在元素的逻辑位置关系。按照这个思路就比较好理解a[5:]结果为空的原因了,因为没有对象可取,所以返回了一个空列表。同样的,如a[2:2]a[3:2]之类的也是这个原因。
对于切片的缺省值问题,在Python的文档里找到了解释:

class slice(stop)
class slice(start, stop[, step])
Return a slice object representing the set of indices specified by range(start, stop, step). The start and step arguments default to None. Slice objects have read-only data attributes start, stop and step which merely return the argument values (or their default). They have no other explicit functionality; however they are used by Numerical Python and other third party extensions. Slice objects are also generated when extended indexing syntax is used. For example: a[start:stop:step] or a[start:stop, i]. See itertools.islice() for an alternate version that returns an iterator.

以及文档对Slicings的说明

A slicing selects a range of items in a sequence object (e.g., a string, tuple or list). Slicings may be used as expressions or as targets in assignment or del statements. The syntax for a slicing:
slicing ::= primary “[“ slice_list “]”
slice_list ::= slice_item (“,” slice_item)* [“,”]
slice_item ::= expression | proper_slice
proper_slice ::= [lower_bound] “:” [upper_bound] [ “:” [stride] ]
lower_bound ::= expression
upper_bound ::= expression
stride ::= expression
There is ambiguity in the formal syntax here: anything that looks like an expression list also looks like a slice list, so any subscription can be interpreted as a slicing. Rather than further complicating the syntax, this is disambiguated by defining that in this case the interpretation as a subscription takes priority over the interpretation as a slicing (this is the case if the slice list contains no proper slice).
The semantics for a slicing are as follows. The primary is indexed (using the same __getitem__() method as normal subscription) with a key that is constructed from the slice list, as follows. If the slice list contains at least one comma, the key is a tuple containing the conversion of the slice items; otherwise, the conversion of the lone slice item is the key. The conversion of a slice item that is an expression is that expression. The conversion of a proper slice is a slice object (see section The standard type hierarchy) whose start, stop and step attributes are the values of the expressions given as lower bound, upper bound and stride, respectively, substituting None for missing expressions.

缺省值严格来说是下界,上界和None。但这也不好解释a[:]的结果。
按我的理解,下界是0,但上界应该与数学分析里的上界类似,所有不小于列表a的最大索引值的数都是上界,而不是上确界,即列表a的最大索引值。在本文的例子中,列表最大索引值是4,那么,只要是大于4的索引值,不管是5,6或者更大的数,对于切片都是一样的,不妨把这个索引值定义为"MAX"。那么a[:]相当于a[0:MAX],但"MAX"值始终比4大,所以切片的结果就包含了列表最后一个元素,也就是结果为['1', '2', '3', '4', '5']。而a[:5]相当于a[0:MAX],结果也就是['1', '2', '3', '4', '5']了。至于a[5:],它相当于a[MAX:MAX],按照元素的逻辑位置的思路,它没有对象可以取得,因此返回了一个空列表[]

坚持原创技术分享,您的支持将鼓励我继续创作!