Python的切片表示法是如何工作的?也就是说:当我编写[x:y:z]、a[:]、a]::2]等代码时,我如何理解哪些元素最终会出现在切片中?请在适当的地方附上参考资料。
另请参见:为什么切片和范围上限是互斥的?
Python的切片表示法是如何工作的?也就是说:当我编写[x:y:z]、a[:]、a]::2]等代码时,我如何理解哪些元素最终会出现在切片中?请在适当的地方附上参考资料。
另请参见:为什么切片和范围上限是互斥的?
当前回答
#!/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)
你可以运行这个脚本并进行实验,下面是我从脚本中获得的一些示例。
+---+---+---+---+---+---+---+---+---+
| 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。
其他回答
在找到这张很棒的桌子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)
如果我们可以将切片与范围联系起来,这很容易理解,因为范围给出了索引。我们可以将切片分为以下两类:
1.无台阶或台阶>0。例如,[i:j]或[i:j:k](k>0)
假设序列为s=[1,2,3,4,5]。
如果0<i<len(s)和0<j<len,则[i:j:k]->范围(i,j,k)
例如,[0:3:2]->范围(0,3,2)->0,2
如果i>len或j>len,则i=len或j=len
例如,[0:100:2]->范围(0,len(s),2)->范围(0,5,2)->0,2,4
如果i<0或j<0,则i=max(0,len(s)+i)或j=max
例如,[0:-3:2]->范围(0,len(s)-3,2)->范围(0,2,2)->0
例如,[0:-1:2]->范围(0,len(s)-1,2)->范围(0,4,2)->0,2
如果未指定i,则i=0
例如,[:4:2]->范围(0,4,2)->范围(4,2)->0,2
如果未指定j,则j=len(s)
例如,[0::2]->范围(0,len(s),2)->范围(0,5,2)->0,2,4
2.步骤<0。例如,[i:j:k](k<0)
假设序列为s=[1,2,3,4,5]。
如果0<i<len(s)和0<j<len,则[i:j:k]->范围(i,j,k)
例如,[5:0:-2]->范围(5,0,-2)->5,3,1
如果i>len或j>len,则i=len(s)-1或j=len(s)-1
例如,[100:0:-2]->范围(len(s)-1,0,-2)->范围(4,0,-2)->4,2
如果i<0或j<0,则i=max(-1,len(s)+i)或j=max(-1len(s)+j)
例如,[-2:-10:-2]->range(len(s)-2,-1,-2)->range(3,-1,-1)->3,1
如果未指定i,则i=len(s)-1
例如,[:0:-2]->范围(len(s)-1,0,-2)->范围(4,0,-2)->4,2
如果未指定j,则j=-1
例如,[2::-2]->范围(2,-1,-2)->2,0
例如,[::-1]->range(len(s)-1,-1,-1)->range(4,-1,1)->4,3,2,1,0
总而言之
使用一点后,我意识到最简单的描述是它与for循环中的参数完全相同。。。
(from:to:step)
其中任何一项都是可选的:
(:to:step)
(from::step)
(from:to)
然后,负索引只需要将字符串的长度添加到负索引中即可理解它。
不管怎样,这对我来说都很有效。。。
在Python中,最基本的切片形式如下:
l[start:end]
其中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]
当从开始切片时,可以省略零索引,而当切片到结束时,可以忽略最终索引,因为它是冗余的,所以不要冗长:
In [5]: l[:3] == l[0:3]
Out[5]: True
In [6]: l[7:] == l[7:len(l)]
Out[6]: True
负整数在相对于集合结尾进行偏移时非常有用:
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]
切片时可以提供超出范围的索引,例如:
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]
请记住,分割集合的结果是一个全新的集合。此外,当在赋值中使用切片表示法时,切片赋值的长度不需要相同。将保留分配切片之前和之后的值,集合将收缩或增长以包含新值:
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]
如果忽略开始索引和结束索引,则将创建集合的副本:
In [14]: l_copy = l[:]
In [15]: l == l_copy and l is not l_copy
Out[15]: True
如果在执行赋值操作时省略了开始和结束索引,则集合的整个内容将替换为引用内容的副本:
In [20]: l[:] = list('hello...')
In [21]: l
Out[21]: ['h', 'e', 'l', 'l', 'o', '.', '.', '.']
除了基本切片外,还可以应用以下符号:
l[start:end:step]
其中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]
使用step提供了在Python中反转集合的有用技巧:
In [25]: l[::-1]
Out[25]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
也可以使用负整数作为步骤,如下例所示:
In[28]: l[::-2]
Out[28]: [9, 7, 5, 3, 1]
然而,使用负值作为步长可能会变得非常混乱。此外,为了成为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]
语法为:
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
还有一个步长值,可用于上述任何一项:
a[start:stop:step] # start through not past stop, by step
要记住的关键点是:stop值表示不在所选切片中的第一个值。因此,停止和开始之间的区别是所选元素的数量(如果步骤为1,则为默认值)。
另一个特点是start或stop可以是负数,这意味着它从数组的末尾开始计数,而不是从开始计数。因此:
a[-1] # last item in the array
a[-2:] # last two items in the array
a[:-2] # everything except the last two items
类似地,步骤可以是负数:
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对程序员很友好。例如,如果您请求一个[:-2],而一个只包含一个元素,则会得到一个空列表而不是一个错误。有时你会更喜欢错误,所以你必须意识到这可能会发生。
与切片对象的关系
切片对象可以表示切片操作,即:
a[start:stop:step]
相当于:
a[slice(start, stop, step)]
根据参数的数量,切片对象的行为也略有不同,类似于range(),即切片(stop)和切片(start,stop[,step])都受支持。要跳过指定给定参数,可以使用None,例如[start:]等同于[sslice(start,None)]或[::-1]等同于[Sslice(None,None,-1)]。
虽然基于:的表示法对简单切片非常有用,但slice()对象的显式使用简化了切片的编程生成。