彻底理解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中利用sqrt()方法进行平方根计算的教程
May 15 Python
python 实现上传图片并预览的3种方法(推荐)
Jul 14 Python
有趣的python小程序分享
Dec 05 Python
Python通过Pygame绘制移动的矩形实例代码
Jan 03 Python
对python同一个文件夹里面不同.py文件的交叉引用方法详解
Dec 15 Python
详解python做UI界面的方法
Feb 27 Python
Python 使用元类type创建类对象常见应用详解
Oct 17 Python
浅谈sklearn中predict与predict_proba区别
Jun 28 Python
python批量处理多DNS多域名的nslookup解析实现
Jun 28 Python
Python-openCV开运算实例
Jul 05 Python
python中温度单位转换的实例方法
Dec 27 Python
Python就将所有的英文单词首字母变成大写
Feb 12 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
初识laravel5
2015/03/02 PHP
php链表用法实例分析
2015/07/09 PHP
php使用str_shuffle()函数生成随机字符串的方法分析
2017/02/17 PHP
php递归函数怎么用才有效
2018/02/24 PHP
PHP变量的作用范围实例讲解
2020/12/22 PHP
关于Javascript模块化和命名空间管理的问题说明
2010/12/06 Javascript
extjs两个tbar问题探讨
2013/08/08 Javascript
js 用CreateElement动态创建标签示例
2013/11/20 Javascript
javascript中call apply 的应用场景
2015/04/16 Javascript
jquery获取节点名称
2015/04/26 Javascript
js确认框confirm()用法实例详解
2016/01/07 Javascript
angular.js之路由的选择方法
2016/09/24 Javascript
JavaScript基本类型值-Undefined、Null、Boolean
2017/02/23 Javascript
JavaScript 巧学巧用
2017/05/23 Javascript
利用jquery去掉时光轴头尾部线条的方法实例
2017/06/16 jQuery
JavaScript函数绑定用法实例分析
2017/11/14 Javascript
JavaScript实现微信号随机切换代码
2018/03/09 Javascript
node.js之基础加密算法模块crypto详解
2018/09/11 Javascript
Vue 配合eiement动态路由,权限验证的方法
2018/09/26 Javascript
15 分钟掌握vue-next响应式原理
2019/10/13 Javascript
[02:56]DOTA2亚洲邀请赛 VG出场战队巡礼
2015/02/07 DOTA
2款Python内存检测工具介绍和使用方法
2014/06/01 Python
Jupyter notebook 启动闪退问题的解决
2020/04/13 Python
Python多个装饰器的调用顺序实例解析
2020/05/22 Python
UGG英国官方网站:UGG UK
2018/02/08 全球购物
应届大学生的推荐信
2013/11/20 职场文书
大学生自荐书范文
2013/12/10 职场文书
管理失职检讨书
2014/02/12 职场文书
2014社区三八妇女节活动方案
2014/03/30 职场文书
教研活动总结
2014/04/28 职场文书
小学竞选班干部演讲稿
2014/08/20 职场文书
2015年置业顾问工作总结
2015/04/07 职场文书
同事打架检讨书
2015/05/06 职场文书
圣诞晚会主持词开场白
2015/05/28 职场文书
干部作风纪律整顿心得体会
2016/01/23 职场文书
自从在 IDEA 中用了热部署神器 JRebel 之后,开发效率提升了 10(真棒)
2021/06/26 Java/Android