彻底理解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计算最小优先级队列代码分享
Dec 18 Python
Python基本数据类型详细介绍
Mar 11 Python
python使用arp欺骗伪造网关的方法
Apr 24 Python
Python实现包含min函数的栈
Apr 29 Python
python并发和异步编程实例
Nov 15 Python
python利用ffmpeg进行录制屏幕的方法
Jan 10 Python
Django REST框架创建一个简单的Api实例讲解
Nov 05 Python
Python pyautogui模块实现鼠标键盘自动化方法详解
Feb 17 Python
基于python 取余问题(%)详解
Jun 03 Python
python实现数字炸弹游戏
Jul 17 Python
Python 操作 MySQL数据库
Sep 18 Python
Python使用for生成列表实现过程解析
Sep 22 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
UCenter中的一个可逆加密函数authcode函数代码
2010/07/20 PHP
PHP获取数组的键与值方法小结
2015/06/13 PHP
php简单截取字符串代码示例
2016/10/19 PHP
php读取qqwry.dat ip地址定位文件的类实例代码
2016/11/15 PHP
php中preg_replace正则替换用法分析【一次替换多个值】
2017/01/17 PHP
php中青蛙跳台阶的问题解决方法
2018/10/14 PHP
Yii框架响应组件用法实例分析
2019/09/04 PHP
window.open()弹出居中的窗口
2007/02/01 Javascript
js类中获取外部函数名的方法与代码
2007/09/12 Javascript
jquery 分页控件实现代码
2009/11/30 Javascript
基于Jquery的简单&amp;简陋Tabs插件代码
2010/02/09 Javascript
深入理解javascript中defer的作用
2013/12/11 Javascript
JavaScript中绑定事件的三种方式及去除绑定
2016/11/05 Javascript
angular.js + require.js构建模块化单页面应用的方法步骤
2017/07/19 Javascript
JavaScript Date对象应用实例分享
2017/10/30 Javascript
vue.js内置组件之keep-alive组件使用
2018/07/10 Javascript
angularJs中ng-model-options设置数据同步的方法
2018/09/30 Javascript
vue将单页面改造成多页面应用的方法
2018/11/25 Javascript
详解基于React.js和Node.js的SSR实现方案
2019/03/21 Javascript
javascript实现图片轮播代码
2019/07/09 Javascript
vue使用微信扫一扫功能的实现代码
2020/04/11 Javascript
JavaScript中继承原理与用法实例入门
2020/05/09 Javascript
解决VUE-Router 同一页面第二次进入不刷新的问题
2020/07/22 Javascript
详解JavaScript数据类型和判断方法
2020/09/04 Javascript
[02:11]2014DOTA2 TI专访VG战队Fenrir:队伍气氛良好
2014/07/11 DOTA
详解Python的Django框架中Manager方法的使用
2015/07/21 Python
python3利用smtplib通过qq邮箱发送邮件方法示例
2017/12/03 Python
python使用正则表达式来获取文件名的前缀方法
2018/10/21 Python
python双向链表原理与实现方法详解
2019/12/03 Python
详解css3中的伪类before和after常见用法
2020/11/17 HTML / CSS
Speedo速比涛德国官方网站:世界领先的泳装品牌
2019/08/26 全球购物
Belstaff英国官方在线商店:Belstaff.co.uk
2021/02/09 全球购物
自荐信格式写作方法有哪些呢
2013/11/20 职场文书
中专药剂专业应届毕的自我评价
2013/12/27 职场文书
中学生运动会口号
2014/06/07 职场文书
师范生求职信
2014/06/14 职场文书