Python切片中的误区与高级用法
众所周知,我们可以通过索引值(或称下标)来查找序列类型(如字符串、列表、元组...)中的单个元素,那么,如果要获取一个索引区间的元素该怎么办呢?
切片(slice)就是一种截取索引片段的技术,借助切片技术,我们可以十分灵活地处理序列类型的对象。通常来说,切片的作用就是截取序列对象,然而,它还有一些使用误区与高级用法,都值得我们注意。所以,本文将主要跟大家一起来探讨这些内容,希望你能学有所获。
事先声明,切片并非列表的专属操作,但因为列表最具有代表性,所以,本文仅以列表为例作探讨。
1、切片的基础用法
列表是 Python 中极为基础且重要的一种数据结构,我曾写过一篇汇总文章(链接见文末)较全面地学习过它。文中详细地总结了切片的基础用法,现在回顾一下:
切片的书写形式:[i : i+n : m] ;其中,i 是切片的起始索引值,为列表首位时可省略;i+n 是切片的结束位置,为列表末位时可省略;m 可以不提供,默认值是1,不允许为0 ,当m为负数时,列表翻转。注意:这些值都可以大于列表长度,不会报越界。
切片的基本含义是:从序列的第i位索引起,向右取到后n位元素为止,按m间隔过滤 。
li = [1, 4, 5, 6, 7, 9, 11, 14, 16]
# 以下写法都可以表示整个列表,其中 X >= len(li)
li[0:X] == li[0:] == li[:X] == li[:] == li[::] == li[-X:X] == li[-X:]
li[1:5] == [4,5,6,7] # 从1起,取5-1位元素
li[1:5:2] == [4,6] # 从1起,取5-1位元素,按2间隔过滤
li[-1:] == [16] # 取倒数第一个元素
li[-4:-2] == [9, 11] # 从倒数第四起,取-2-(-4)=2位元素
li[:-2] == li[-len(li):-2] == [1,4,5,6,7,9,11] # 从头开始,取-2-(-len(li))=7位元素
# 步长为负数时,列表先翻转,再截取
li[::-1] == [16,14,11,9,7,6,5,4,1] # 翻转整个列表
li[::-2] == [16,11,7,5,1] # 翻转整个列表,再按2间隔过滤
li[:-5:-1] == [16,14,11,9] # 翻转整个列表,取-5-(-len(li))=4位元素
li[:-5:-3] == [16,9] # 翻转整个列表,取-5-(-len(li))=4位元素,再按3间隔过滤
# 切片的步长不可以为0
li[::0] # 报错(ValueError: slice step cannot be zero)
上述的某些例子对于初学者(甚至很多老手)来说,可能还不好理解。我个人总结出两条经验:(1)牢牢记住公式[i : i+n : m] ,当出现缺省值时,通过想象把公式补全;(2)索引为负且步长为正时,按倒数计算索引位置;索引为负且步长为负时,先翻转列表,再按倒数计算索引位置。
2、切片是伪独立对象
切片操作的返回结果是一个新的独立的序列。以列表为例,列表切片后得到的还是一个列表,占用新的内存地址。
当取出切片的结果时,它是一个独立对象,因此,可以将其用于赋值操作,也可以用于其它传递值的场景。但是,切片只是浅拷贝,它拷贝的是原列表中元素的引用,所以,当存在变长对象的元素时,新列表将受制于原列表。
li = [1, 2, 3, 4]
ls = li[::]
li == ls # True
id(li) == id(ls) # False
li.append(li[2:4]) # [1, 2, 3, 4, [3, 4]]
ls.extend(ls[2:4]) # [1, 2, 3, 4, 3, 4]
# 下例等价于判断li长度是否大于8
if(li[8:]):
print("not empty")
else:
print("empty")
# 切片列表受制于原列表
lo = [1,[1,1],2,3]
lp = lo[:2] # [1, [1, 1]]
lo[1].append(1) # [1, [1, 1, 1], 2, 3]
lp # [1, [1, 1, 1]]
由于可见,将切片结果取出,它可以作为独立对象使用,但是也要注意,是否取出了变长对象的元素。
3、切片可作为占位符
切片既可以作为独立对象被“取出”原序列,也可以留在原序列,作为一种占位符使用。
对于列表来说,使用切片作为占位符,同样能够实现拼接列表的效果。特别需要注意的是,给切片赋值的必须是可迭代对象。
li = [1, 2, 3, 4]
# 在头部拼接
li[:0] = [0] # [0, 1, 2, 3, 4]
# 在末尾拼接
li[len(li):] = [5,7] # [0, 1, 2, 3, 4, 5, 7]
# 在中部拼接
li[6:6] = [6] # [0, 1, 2, 3, 4, 5, 6, 7]
# 给切片赋值的必须是可迭代对象
li[-1:-1] = 6 # (报错,TypeError: can only assign an iterable)
li[:0] = (9,) # [9, 0, 1, 2, 3, 4, 5, 6, 7]
li[:0] = range(3) # [0, 1, 2, 9, 0, 1, 2, 3, 4, 5, 6, 7]
上述例子中,若将切片作为独立对象取出,那你会发现它们都是空列表,即 li[:0]== li[len(li):] == li [6 : 6]==[] ,我将这种占位符称为“纯占位符”,对纯占位符赋值,并不会破坏原有的元素,只会在特定的索引位置中拼接进新的元素。删除纯占位符时,也不会影响列表中的元素。
与“纯占位符”相对应,“非纯占位符”的切片是非空列表,对它进行操作(赋值与删除),将会影响原始列表。如果说纯占位符可以实现列表的拼接,那么,非纯占位符可以实现列表的替换。
li = [1, 2, 3, 4]
# 不同位置的替换
li[:3] = [7,8,9] # [7, 8, 9, 4]
li[3:] = [5,6,7] # [7, 8, 9, 5, 6, 7]
li[2:4] = ['a','b'] # [7, 8, 'a', 'b', 6, 7]
# 非等长替换
li[2:4] = [1,2,3,4] # [7, 8, 1, 2, 3, 4, 6, 7]
li[2:6] = ['a'] # [7, 8, 'a', 6, 7]
# 删除元素
del li[2:3] # [7, 8, 6, 7]
切片占位符可以带步长,从而实现连续跨越性的替换或删除效果。需要注意的是,这种用法只支持等长替换。
li = [1, 2, 3, 4, 5, 6]
li[::2] = ['a','b','c'] # ['a', 2, 'b', 4, 'c', 6]
li[::2] = [0]*3 # [0, 2, 0, 4, 0, 6]
li[::2] = ['w'] # 报错,attempt to assign sequence of size 1 to extended slice of size 3
del li[::2] # [2, 4, 6]
4、更多思考
其它编程语言是否有类似于 Python 的切片操作呢?有什么差异?
Python切片中的误区与高级用法的更多相关文章
- Python进阶:切片的误区与高级用法
2018-12-31 更新声明:切片系列文章本是分三篇写成,现已合并成一篇.合并后,修正了一些严重的错误(如自定义序列切片的部分),还对行文结构与章节衔接做了大量改动.原系列的单篇就不删除了,毕竟也是 ...
- 简学Python第七章__class面向对象高级用法与反射
Python第七章__class面向对象高级用法与反射 欢迎加入Linux_Python学习群 群号:478616847 目录: Python中关于oop的常用术语 类的特殊方法 元类 反射 一.P ...
- Python 内置函数sorted()在高级用法
对于Python内置函数sorted(),先拿来跟list(列表)中的成员函数list.sort()进行下对比.在本质上,list的排序和内建函数sorted的排序是差不多的,连参数都基本上是一样的. ...
- Jmeter 中JSON Path Extractor高级用法
好久没玩jemter了,由于项目原因又重新拾起.在使用JSON Path Extractor(jmeter 4.0已经默认支持了,4.0以下要自行安装插件)时,可以进行条件过滤,不用再自行写shell ...
- shell中echo基础及高级用法详解-渐入佳境
--作者:飞翔的小胖猪 --创建时间:2021年2月19日 1.1 基础用法 echo命令用来输出文本,在shell脚本中用来输出提示信息用的比较多. 单引号:原样输出所有的内容,不用转义就能输出特殊 ...
- oracle中group by的高级用法
简单的group by用法 select c1,sum(c2) from t1 where t1<>'test' group by c1 having sum(c2)>100; ro ...
- python的扩展包requests的高级用法
Python 标准库中的 urllib2 模块提供了你所需要的大多数 HTTP 功能,但是它的 API 太渣了.它是为另一个时代.另一个互联网所创建的.它需要巨量的工作,甚至包括各种方法覆盖,来完成最 ...
- python 爬虫2 Urllib库的高级用法
1.设置Headers 有些网站不会同意程序直接用上面的方式进行访问,如果识别有问题,那么站点根本不会响应,所以为了完全模拟浏览器的工作,我们需要设置一些Headers 的属性. import url ...
- python列表中enumerate和zip函数用法
enumerate: 定义:enumerate() 函数用于将一个可遍历的数据对象(如列表.元组或字符串)组合为一个索引序列,同时列出数据和数据下标 例子: list1 =[89,98,00,75,6 ...
随机推荐
- 【带着canvas去流浪(9)】粒子动画
目录 一. 粒子特效 二. 开发中遇到的问题 2.1 卡顿 2.2 轨迹 2.3 复位 2.4 防护层 2.5 二维向量类 三. 实现讲解 3.1 粒子类的update方法 3.2 粒子群的绘制 3. ...
- MySQL逻辑控制语句的使用
一.IF语句 1). IF(expr1,expr2,expr3) 如果expr1为true则结果为expr2否则为expr3 -->相当于三元运算符 ...
- [Spring]:java.lang.NoSuchMethodError: 'java.lang.String javax.annotation.Resource.lookup()'
错误信息 11月 05, 2019 9:32:15 下午 org.springframework.test.context.TestContextManager prepareTestInstance ...
- 【Untiy】完美解决Untiy Package Manager无限加载的问题
直接上干货 打开记事本,复制一下zhei个 @echo offset HTTP_PROXY=127.0.0.1set HTTPS_PROXY=127.0.0.1start "" & ...
- 基于C# 调用百度AI 人脸识别
一.设置 登录百度云控制台,添加应用-添加人脸识别,查找,对比等. 记住API Key和Secret Key 二.创建Demo程序 1.使用Nuget安装 Baidu.AI 和 Newtonsoft. ...
- SQL Server查询数据库近期执行的SQL语句
SELECT TOP 1000 ST.text AS '执行的SQL语句', QS.execution_count AS '执行次数', QS.total_ela ...
- centos python3 的 卸载 删除
卸载/删除python 3.4看到网上说慎用 apt-get remove和 yum remove ,因此不敢用此类命令用卸载了(以后阿里云服务器快过期不用了的时候可以试一下,看看系统是否会崩,哈哈) ...
- ElasticSearch7 设置外网访问失败
elasticsearch外网访问9200端口失败,bootstrap checks failed,the default discovery settings are unsuitable for ...
- bps和pps
bps,比特率指的是每秒传输比特数 在实际所说的1M带宽的意思是1Mbps(是兆比特每秒Mbps不是兆字节每秒MBps) pps(数据包每秒),常用的网络吞吐率的单位(即每秒发送多少个分组数据包),网 ...
- 飞思卡尔K60时钟分析
推荐:NXP官方软件config tool,图形化界面可导出代码 K60芯片的时钟系统由振荡器(OSC).实时振荡器(RTC OSC).多功能时钟发生器(MCG).系统集成模块(SIM)和电源管理器( ...