彻底理解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生成验证码实例
Aug 21 Python
学习python之编写简单简单连接数据库并执行查询操作
Feb 27 Python
Python用UUID库生成唯一ID的方法示例
Dec 15 Python
Python的爬虫框架scrapy用21行代码写一个爬虫
Apr 24 Python
Python 处理数据的实例详解
Aug 10 Python
Centos7 Python3下安装scrapy的详细步骤
Mar 15 Python
Python实现的端口扫描功能示例
Apr 08 Python
Pandas 对Dataframe结构排序的实现方法
Apr 10 Python
Python使用pylab库实现绘制直方图功能示例
Jun 01 Python
Python设计模式之策略模式实例详解
Jan 21 Python
python 安装移动复制第三方库操作
Jul 13 Python
pyqt5打包成exe可执行文件的方法
May 14 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
PHP生成迅雷、快车、旋风等软件的下载链接代码实例
2014/05/12 PHP
PHP入门之常量简介和系统常量
2014/05/12 PHP
详解thinkphp实现excel数据的导入导出(附完整案例)
2016/12/29 PHP
PHP使用file_get_contents发送http请求功能简单示例
2018/04/29 PHP
PHP连接及操作PostgreSQL数据库的方法详解
2019/01/30 PHP
Javascript 变量作用域 两个可能会被忽略的小特性
2010/03/23 Javascript
url参数中有+、空格、=、%、&amp;、#等特殊符号的问题解决
2013/05/15 Javascript
怎么选择Javascript框架(Javascript Framework)
2013/11/22 Javascript
点击标签切换和自动切换DIV选项卡
2014/08/10 Javascript
javascript使用数组的push方法完成快速排序
2014/09/15 Javascript
avalonjs制作响应式瀑布流特效
2015/05/06 Javascript
利用JS提交表单的几种方法和验证(必看篇)
2016/09/17 Javascript
快速实现JS图片懒加载(可视区域加载)示例代码
2017/01/04 Javascript
简单易懂的天气插件(代码分享)
2017/02/04 Javascript
Vue.js原理分析之observer模块详解
2017/02/17 Javascript
JavaScript中的this陷阱的最全收集并整理(没有之一)
2017/02/21 Javascript
Vue2路由动画效果的实现代码
2017/07/10 Javascript
JS运动特效之任意值添加运动的方法分析
2018/01/24 Javascript
vue中watch的用法汇总
2020/12/28 Vue.js
js定时器出现第一次延迟的原因及解决方法
2021/01/04 Javascript
Python中tell()方法的使用详解
2015/05/24 Python
python 处理string到hex脚本的方法
2018/10/26 Python
Python 运行 shell 获取输出结果的实例
2019/01/07 Python
python原类、类的创建过程与方法详解
2019/07/19 Python
使用python制作游戏下载进度条的代码(程序说明见注释)
2019/10/24 Python
Jupyter notebook设置背景主题,字体大小及自动补全代码的操作
2020/04/13 Python
Python中的__init__作用是什么
2020/06/09 Python
浅谈Python中的模块
2020/06/10 Python
python2和python3哪个使用率高
2020/06/23 Python
html5手机端页面可以向右滑动导致样式受影响的问题
2018/06/20 HTML / CSS
澳大利亚票务和娱乐市场领导者:Ticketmaster
2017/03/03 全球购物
科室工作的个人自我评价
2013/10/30 职场文书
优秀的计算机专业求职信范文
2013/12/27 职场文书
蟋蟀的住宅教学反思
2014/04/26 职场文书
社会工作专业求职信
2014/07/15 职场文书
python数字图像处理之图像的批量处理
2022/06/28 Python