彻底理解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提取Linux内核源代码的目录结构实现方法
Jun 24 Python
多个应用共存的Django配置方法
May 30 Python
查看TensorFlow checkpoint文件中的变量名和对应值方法
Jun 14 Python
python K近邻算法的kd树实现
Sep 06 Python
python队列原理及实现方法示例
Nov 27 Python
python计算auc的方法
Sep 09 Python
详解Python模块化编程与装饰器
Jan 16 Python
pandas数据分组groupby()和统计函数agg()的使用
Mar 04 Python
python 遍历磁盘目录的三种方法
Apr 02 Python
python3实现常见的排序算法(示例代码)
Jul 04 Python
Python OpenCV之常用滤波器使用详解
Apr 07 Python
Python sklearn分类决策树方法详解
Sep 23 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
对于ThinkPHP框架早期版本的一个SQL注入漏洞详细分析
2014/07/04 PHP
php实现微信公众平台账号自定义菜单类
2014/12/02 PHP
PHP浮点数精度问题汇总
2015/05/13 PHP
PHP中include()与require()的区别说明
2017/02/14 PHP
js如何获取兄弟、父类等节点
2014/01/06 Javascript
Js+Jq获取URL参数的集中方法示例代码
2014/05/20 Javascript
JavaScript弹出窗口方法汇总
2014/08/12 Javascript
深入浅析AngularJS和DataModel
2016/02/16 Javascript
jquery实现无刷新验证码的简单实例
2016/05/19 Javascript
JS封装通过className获取元素的函数示例
2016/12/20 Javascript
微信小程序 image组件binderror使用例子与js中的onerror区别
2017/02/15 Javascript
Javascript实现登录记住用户名和密码功能
2017/03/22 Javascript
Bootstrap Tooltip显示换行和左对齐的解决方案
2017/10/11 Javascript
JS删除数组里的某个元素方法
2018/02/03 Javascript
vue-cli 使用axios的操作方法及整合axios的多种方法
2018/09/12 Javascript
微信小程序template模版的使用方法
2019/04/13 Javascript
详解vue更改头像功能实现
2019/04/28 Javascript
微信小程序8种数据通信的方式小结
2020/02/03 Javascript
微信小程序开发之获取用户手机号码(php接口解密)
2020/05/17 Javascript
原生js滑动轮播封装
2020/07/31 Javascript
vue自定义组件(通过Vue.use()来使用)即install的用法说明
2020/08/11 Javascript
详解Vue的七种传值方式
2021/02/08 Vue.js
详细探究Python中的字典容器
2015/04/14 Python
python 实现交换两个列表元素的位置示例
2019/06/26 Python
基于python实现雪花算法过程详解
2019/11/16 Python
Python3.7在anaconda里面使用IDLE编译器的步骤详解
2020/04/29 Python
Python的信号库Blinker用法详解
2020/12/31 Python
jupyter 添加不同内核的操作
2021/02/06 Python
CSS3使用transition实现的鼠标悬停淡入淡出
2015/01/09 HTML / CSS
用HTML5的canvas实现一个炫酷时钟效果
2016/05/20 HTML / CSS
String是最基本的数据类型吗?
2013/06/13 面试题
餐饮收银员岗位职责
2014/02/07 职场文书
2014年安全保卫工作总结
2014/11/13 职场文书
教师年终个人总结
2015/02/11 职场文书
深入理解java.lang.String类的不可变性
2021/06/27 Java/Android
WinServer2012搭建DNS服务器的方法步骤
2022/06/10 Servers