彻底理解Python list切片原理


Posted in Python onOctober 27, 2017

关于list的insert函数

list#insert(ind,value)在ind元素前面插入value

首先对ind进行预处理:如果ind<0,则ind+=len(a),这样一来ind就变成了正数下标

 预处理之后,

 当ind<0时,ind=0,相当于头部插入
 当ind>len(a)时,ind=len(a),相当于尾部插入

切片实例

Python中的列表切片非常灵活,要根据表象来分析它的内在机理,这样用起来才能溜。

下标可以为负数有利有弊,好处是使用起来更简便,坏处是当我下表越界了我也不知道反倒发生奇奇怪怪的错误。

print str[0:3] #截取第一位到第三位的字符
print str[:] #截取字符串的全部字符
print str[6:] #截取第七个字符到结尾
print str[:-3] #截取从头开始到倒数第三个字符之前
print str[2] #截取第三个字符
print str[-1] #截取倒数第一个字符
print str[::-1] #创造一个与原字符串顺序相反的字符串
print str[-3:-1] #截取倒数第三位与倒数第一位之前的字符
print str[-3:] #截取倒数第三位到结尾
print str[:-5:-3] #逆序截取

可见,列表的下标有三个参数:beg(起始下标),end(终止下标),delta(变化量)

  1. 当delta小于0时,beg默认为len(array)-1,end默认为开头之前。
  2. 当delta大于0时,beg默认为0,end默认为最末之后。
  3. 当delta未给出时:delta默认为1

这个代码示例演示了大概原理,学习一件事物,先学习它的表象,然后分析它的内在实现,最后查看源代码仔细推敲它到底是怎么实现的。

需要注意的是,列表切片产生的是列表的副本,与原列表不是同一份空间。

x=[1,2,3]
y=x[:]
x[0]=-1
print(y) #输出[1,2,3]

列表切片写操作

接下来探究切片的写操作

>>> x=[1,2,3,4,5]
>>> x[2:0]=100  #在2后面插入若干个元素,应该用列表
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: can only assign an iterable
>>> x[2:0]=[100]
>>> x
[1, 2, 100, 3, 4, 5]
>>> del x[2:3]  #删除切片
>>> x
[1, 2, 3, 4, 5]
>>> x[2:1]=[100] #对于切片x[from:to],会进行预处理to=max(from+1,to)
>>> x
[1, 2, 100, 3, 4, 5]
>>> del x[2:0]  #对于切片del操作,如果from>to,不执行任何操作
>>> x
[1, 2, 100, 3, 4, 5]
>>> del x[2:1]
>>> x
[1, 2, 100, 3, 4, 5]
>>> del x[2:3]
>>> x
[1, 2, 3, 4, 5]
>>> x[2:4]=None
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: can only assign an iterable
>>> x[2:4]=[None]
>>> x
[1, 2, None, 5]

对列表切片进行深入理解:

def between(beg, end, mid):
 # 判断mid是否位于begin和end之间
 return end > mid >= beg or end < mid <= beg


def get_slice(a, beg, end, delta=1):
 # 数组切片get方式
 if delta == 0: raise ValueError("slice step cannot be 0")
 # 将负数下标转化一下
 if beg < 0: beg += len(a)
 if end < 0: end += len(a)
 # 如果转化完成之后依然不在合法范围内,则返回空列表
 if beg < 0 and end < 0 or beg >= len(a) and end >= len(a): return []
 # 如果方向不同,则返回空列表
 if (end - beg) * delta <= 0: return []
 # 将越界的部分进行裁剪
 beg = max(0, min(beg, len(a) - 1))
 end = max(-1, min(end, len(a)))
 ans = []
 i = beg
 while between(beg, end, i):
  ans.append(a[i])
  i += delta
 return ans


def set_slice(a, li, beg, end, delta=1):
 if delta == 0: raise ValueError("slice step cannot be 0")
 if delta == 1:
  # 如果delta==1,那么li的长度可以随意
  if beg < 0: beg += len(a)
  if end < 0: end += len(a)
  beg = max(0, min(beg, len(a) - 1))
  end = max(-1, min(end, len(a)))
  for i in range(beg, end):
   del a[beg]
  for i in reversed(li):
   a.insert(beg, i)
 else:
  # delta!=1,相当于替换
  if len(get_slice(a, beg, end, delta)) != len(li): raise ValueError("array don't match")
  if len(li) == 0: return
  if beg < 0: beg += len(a)
  if end < 0: end += len(a)
  beg = max(0, min(beg, len(a) - 1))
  # 用li中的全部元素逐一替换
  for ind, value in enumerate(li):
   a[ind * delta + beg] = value


def test_getSlice():
 a = list(range(10))
 import random
 for i in range(10):
  beg = random.randint(-15, 15)
  end = random.randint(-15, 15)
  delta = 0
  while delta == 0: delta = random.randint(-15, 15)
  print(len(get_slice(a, beg, end, delta)) == len(a[beg:end:delta]), beg, end, delta)


def test_setSlice():
 import random
 for i in range(10):
  a = list(range(10))
  beg = random.randint(-15, 15)
  end = random.randint(-15, 15)
  delta = 0
  while delta == 0: delta = random.randint(-5, 5)
  sz = len(a[beg:end:delta])
  if delta == 1: sz = random.randint(0, 4)
  li = [random.randint(0, 100) for i in range(sz)]
  set_slice(a, li, beg, end, delta)
  mine = a
  a = list(range(10))
  a[beg:end:delta] = li
  print(a == mine)


test_setSlice()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python实现二叉搜索树
Feb 03 Python
Python处理Excel文件实例代码
Jun 20 Python
pycharm远程调试openstack的图文教程
Nov 21 Python
Python3.8中使用f-strings调试
May 22 Python
python中的TCP(传输控制协议)用法实例分析
Nov 15 Python
Python3.7 基于 pycryptodome 的AES加密解密、RSA加密解密、加签验签
Dec 04 Python
python多进程重复加载的解决方式
Dec 13 Python
使用Python发现隐藏的wifi
Mar 04 Python
Pycharm中安装Pygal并使用Pygal模拟掷骰子(推荐)
Apr 08 Python
通过python 执行 nohup 不生效的解决
Apr 16 Python
Python抓包并解析json爬虫的完整实例代码
Nov 03 Python
Prometheus开发中间件Exporter过程详解
Nov 30 Python
Python在不同目录下导入模块的实现方法
Oct 27 #Python
Django视图之ORM数据库查询操作API的实例
Oct 27 #Python
浅谈python函数之作用域(python3.5)
Oct 27 #Python
python+pyqt实现右下角弹出框
Oct 26 #Python
python中模块的__all__属性详解
Oct 26 #Python
Python内建函数之raw_input()与input()代码解析
Oct 26 #Python
python分布式环境下的限流器的示例
Oct 26 #Python
You might like
收音机怀古---春雷3P7图片欣赏
2021/03/02 无线电
PHP+MYSQL会员系统的登陆即权限判断实现代码
2011/09/23 PHP
深入理解PHP内核(二)之SAPI探究
2015/11/10 PHP
document.compatMode介绍
2009/05/21 Javascript
两个比较有用的Javascript工具函数代码
2010/02/17 Javascript
jquery插件之easing使用
2010/08/19 Javascript
JavaScrip单线程引擎工作原理分析
2010/09/04 Javascript
javascript中encodeURI和decodeURI方法使用介绍
2013/05/06 Javascript
jQuery调用AJAX时Get和post公用的乱码解决方法实例说明
2013/06/04 Javascript
jQuery中用dom操作替代正则表达式
2014/12/29 Javascript
javascript实现九宫格相加数值相等
2020/05/28 Javascript
ES6中Proxy与Reflect实现重载(overload)的方法
2017/03/30 Javascript
ionic实现底部分享功能
2017/05/11 Javascript
JS实现不用中间变量temp 实现两个变量值得交换方法
2018/02/04 Javascript
微信小程序实现分享到朋友圈功能
2018/07/19 Javascript
vue使用canvas实现移动端手写签名
2020/09/22 Javascript
如何利用Fabric自动化你的任务
2016/10/20 Python
基于python的Tkinter编写登陆注册界面
2017/06/30 Python
python+selenium实现163邮箱自动登陆的方法
2017/12/31 Python
十分钟利用Python制作属于你自己的个性logo
2018/05/07 Python
Python多重继承的方法解析执行顺序实例分析
2018/05/26 Python
Django 如何使用日期时间选择器规范用户的时间输入示例代码详解
2020/05/22 Python
Python pytesseract验证码识别库用法解析
2020/06/29 Python
德国大型的家具商店:Pharao24.de
2016/10/02 全球购物
英国工艺品购物网站:Minerva Crafts
2018/01/29 全球购物
小学教师的个人自我鉴定
2013/10/24 职场文书
小学优秀班主任事迹材料
2014/05/17 职场文书
2014院党委领导班子对照检查材料思想汇报
2014/09/24 职场文书
个人学习党的群众路线教育实践活动心得体会
2014/11/05 职场文书
2014年计划生育工作总结
2014/11/14 职场文书
放弃继承权公证书
2015/01/23 职场文书
党员个人总结范文
2015/02/14 职场文书
2015年医德考评自我评价
2015/03/03 职场文书
2019财务转正述职报告
2019/06/27 职场文书
一篇文章弄懂MySQL查询语句的执行过程
2021/05/07 MySQL
MySql 缓存查询原理与缓存监控和索引监控介绍
2021/07/02 MySQL