Python的序列切片

       Python提供了一种把序列切成小块的操作,称为切片(slice)操作,其本质是访问由序列中的某些元素所构成的子集。Python的序列数据结构都支持切片操作,如列表、元组、字符串等,切片操作可以说是日常应用中最常使用的Python特性之一。
(1)基本写法
sequence[start : end]
sequence:表示序列,可以是列表、字符串、元组等;
start:起始索引;
end:结束索引。
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = a[0:5]
c = a[:]
d = a[5:15]
print('a=', a, 'b=', b, 'c=', c, 'd=', d)
     
     
输出结果:
a= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b= [1, 2, 3, 4, 5]
c= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
d= [6, 7, 8, 9, 10]
可以看出:
       1)序列a没有变化,说明切片(slice)操作不改变原序列,而是生成一个新序列;
       2)序列b的结果说明从头切片的话,索引值是从0开始的,另外start所指元素在切片结果内,而end所指元素则不包括在切片结果中,说明切片[start:end]是一个半闭区间
       3)序列c结果说明从头切片的话,start索引值0可以省略,如果取到序列末尾,end也应该省略这样更清爽;
       4)序列d结果说明索引范围不能越过序列本身边界,越过边界自动取边界值(Python3特性,在Python2会报错)。
(2)负值索引
       若要从序列尾部向前算,则可以用负值表示相关偏移量。
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = a[:-1]
c = a[-3:]
print('b=', b, 'c=', c)
      
      
输出结果:
b= [1, 2, 3, 4, 5, 6, 7, 8, 9]
c= [8, 9, 10]
可以看出:
       1)序列b比a少了最后一个元素,说明:-1表示最后一个元素
       2)序列c结果表明:用-n代表倒数第n个元素,并且即使start索引是负数,切片顺序也是从前往后的
(3)反向和步进操作
       除了基本写法外,Python还提供了sequence[start : end : stride]的写法,以实现步进式切割。看示例:
s = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a = s[::2]
b = s[::-1]
c = s[::-2]
print('a=', a, 'b=', b, 'c=', c)
      
      
输出结果:
a= [1, 3, 5, 7, 9]
b= [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
c= [10, 8, 6, 4, 2]
      可以看出:
       1)序列a为序列s每隔2个元素进行取值,说明有stride的话按步进值间隔取序列中的元素;
       2)序列b与序列s为反向,说明步进值为负值的话,实施的是反向操作,从序列末尾从后往前取元素。
       3)序列c的结果说明使用负数布进值,除了按照反向操作外,也按照数字大小间隔取元素。

一般的应用情况下,与正向切片相比,反向切片和步进操作使用相对较少,但需要用的话,是非常好用且异常简洁的。看一个反向操作的经典应用:回文字符串判断 回文字符串是指aba、abba、cccbccc、aaaa这种左右对称的字符串。
先看C语言的经典实现:
bool fun(char str[])
{
int i, j, n;
n = strlen(str);
for (i = 0, j = n-1; i <= (n-1)/2; i++, j--)
{
if (str[i] != str[j])
break;
}
if i > j
return True;
else
return False;
}
再看Python中利用反向切片操作的实现,异常简洁:
def fun(str):
return str == str[::-1]
(4)不要同时指定start,end和stride
       按照《Effective Python》一书中的说法,切片操作既有start和end,又有stride的话,可能会令人费解,牺牲了可读性,尤其是有负值索引和负的步进值情况下。看示例:
s = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a = s[-2:2:-2]
print(a)
       
       
输出结果:
a= [9, 7, 5]
       上例意思是从序列s倒着数第二个元素(包含)到序列s正着数第二个元素(不包含)之间的范围(注意切片操作范围是半闭区间)按步进值2进行反向切片,确实有点绕口,但也还算好懂。
       改进方式可以考虑使用两条赋值语句代替,具体方法可是先做范围切片,再做步进切片,也可以先做步进切片,再做范围切片。个人认为先范围再步进的方法更好。
s = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a = s[-2:2:-2]
b = s[3:len(s)-1]
c = b[::-2]
print('a=', a, 'c=', c)
      
      
输出结果:
a= [9, 7, 5]
c= [9, 7, 5]
       上例中b和c先对s做范围切割,再做步进切割。
       实际工作中如果思路清晰,切片使用熟练,同指定start,end和stride无不妥,毕竟就3个参数而已。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值