问题的起因
今天在写代码的时候,看到一个比较有意思的写法。假设我们有一个list,它的内容是a = [0, 1, 2, 3, 4, 5, 6, 7, 8 ,9]。如果我们取它反转后的结果,一般我们头脑里默认想到的无非就是reverse这样的方法了。但是它还有一种写法:a[::-1],输出的结果是和当前的结果相反。在某些情况下,它的应用还是比较有意思的。就想针对这一块总结一下。
slice在python中的应用
在python中,list, tuple以及字符串等可以遍历访问的类型都可以应用slice访问。slice本身的意思是指切片,在这些可以遍历访问的类型中截取其中的某些部分。比如如下的代码:
>>> l = range(10) >>> l [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> l[1:5] [1, 2, 3, 4]
首先,我们通过range(10) 生成一个从0到9的列表。在这个列表中取[1:5]的时候返回的是索引1到4的。所以,我们发现他们所取的slice是一个半开半闭的区间。l[a:b]==> l[a, b).
前面这种情况下,是我们已知列表的长度,然后取他们的某个区段,如果我们不知道列表的长度,或者列表长度的获取比较麻烦呢?如果用其他的语言,我们可能考虑这个列表是否应该有一个list.length之类的属性了。在这里,有另外一个办法来取得:
>>> l[-1] 9 >>> l[1:-1] [1, 2, 3, 4, 5, 6, 7, 8] >>> l[2:-2] [2, 3, 4, 5, 6, 7]
我们可以看到如果要取列表中的最后一个元素,可以用l[-1]的方式,如果从后面向前,可以依次取l[-2], l[-3]...
既然我们前面提到,在列表中slice是取的一个前面闭合后面开放的区间,也就是说我在l[a:b]的时候,索引值为b的那个元素是不包含在结果中的。如果我们想要包含后面的值那么该怎么办呢?
这个问题可以分为几种情况来考虑,一个是加入b本身长度比较小,那么我们取l[a:b+1]就好了。比如说如下:
>>> l[1:3] [1, 2] >>> l[1:4] [1, 2, 3]
如果我们想把索引值为3的也包含进来,我们就用l[1:4]就行了。那么,对于处在列表末尾的元素呢?用过c, java开发的人会想到,按照这种方式会不会导致访问数组越界呢?我们试试看吧:
>>> len(l) 10 >>> l[1:10] [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> l[1:11] [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> l[1:12] [1, 2, 3, 4, 5, 6, 7, 8, 9]
len(l)返回l的长度。我们原来潜意识的认为,既然数组长度为10,那么我们访问的索引最大值也不过为l[9]。实际上,在python这里,可以列出的访问下标值超出数组长度范围,只不过仅仅返回能遍历到的元素而已。
当然,我们还有另外一种办法:
>>> l[1:] [1, 2, 3, 4, 5, 6, 7, 8, 9]
这种方式就完全将前面索引到数组末尾的元素都包含进来了。
这样,我们要包含整个数组中的元素就可以采用如下的几种方式:
>>> l[0:] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> l[:] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> l [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
从前面我们用l[a:b] 的方式来访问元素来看,我们这里a, b取的值要么满足0<= a <= b 或者 a >= 0 b < 0。实际上,a所对应元素的位置总是在b所对应位置的后面。那么,如果我们把他们的顺序倒过来一下会怎么样呢?比如说:
>>> l[5:2] [] >>> l[-1:3] []
在这里,我们发现,如果实际取的元素先从右边开始然后到左边的话,并不是我们所期望的返回一个倒过来的数组,而是返回一个空的数组。我举的这个例子有什么用呢?别急,看了后面那一节你就知道了。
理解extended slice
前面那一部分相对来说还是比较好理解的。现在,如果我们有一些其他的要求,比如说,我们想返回数组里面索引为奇数的元素,或者索引为偶数的元素,那么该怎么办呢?
我们可以有几种办法来做,其中的一种就是采用extended slice,一个典型的解决方法如下:
>>> l[::2] [0, 2, 4, 6, 8] >>> l[1::2] [1, 3, 5, 7, 9] >>>
前面这种包含两个冒号的样式是怎么回事呢?
实际上,我们这边第一个冒号隔开的这两个部分和前面的意思是一样的,就是指定数组中间元素的区间。所以前面第一个l[::2]前面就是指的整个数组的元素。而后面那个部分则是指的一个步长。这表示什么意思呢?就是既然我们前面指定的是整个数组,那么它就是从0开始,然后每次访问后面相邻的元素。而设置为2之后呢,则访问后面和它距离为2的元素,而不是直接相邻的元素。这样,我们也就容易理解l[1::2],它就是从元素1开始到结尾的元素集合里取间隔为2的这些元素。
到这一步,就离我们理解前面那个古怪的l[::-1]很接近了。我们前面的这个取步长是将步长设置为正数,所以在取元素的集合里它表示从左到右的取指定步长覆盖的元素。如果我们将步长设置为负数呢?我们来看:
>>> l[1:9:-1] [] >>> l[9:1:-1] [9, 8, 7, 6, 5, 4, 3, 2]
有了前面这一部分的代码,相信就不难理解了。我们取区间[1, 9),结果取步长为-1的时候返回的是一个空的集合。而我们取9到1的时候,步长为-1取出来了倒序的数组。这是因为如果我们指定的步长为负数的话,那么它必须和数据指定的区间方向一致。也就是说,如果我们前面指定的区间是从数组小的索引到大的索引,那么我指定的步长必然也要从小到大。所以必须为正数。而如果我们指定的区间是从后面往前的话,则步长必须指定为负数。否则返回的结果都是空的数组。
总结
有了前面那么多的讨论,我们再来看数组的slice访问。他们无非就是这么几个情况,在l[a:b]的情况下,必须保证a所在的索引位置在前,b所在的索引位置在后,否则返回结果为空。在l[a:b:step]的情况下,我们首先要根据a, b的位置来判断方向,a在前,b在后的话,step应该为正,否则应该为负。不符合这些情况的话,则返回空的数组。也就是说,看a, b的位置来确定方向,不要犯方向性的错误,否则就竹篮打水一场空了:)
相关推荐
答:可以使用Python的字符串slice操作来反转字符串,使用"aStr"[::-1]语法。 列表操作知识点: 7. 将字符串 "k:1 |k1:2|k2:3|k3:4",处理成字典 {k:1,k1:2,...}? 答:可以使用Python的字符串split()函数来分割...
在Python的期末复习中,以下几个核心知识点是必须掌握的: 1. **Python语言特点与书写规范**: - Python是解释型语言,这意味着代码无需编译即可执行。 - 它是开源的,提供了一个广泛的社区支持和丰富的标准库。 ...
### Python新手必会的9个Python教程知识点详解 #### 一、清理字符串输入 在编程过程中,特别是涉及用户输入的应用场景中,清理字符串是非常重要的一步。文档中提到了几种清理字符串的方法,包括基本的大小写转换、...
这个过程通常包括以下几个步骤: 1. 数据预处理:清洗和标准化输入数据。 2. 选择核函数:常见的核函数有高斯(Gaussian)、Epanechnikov、三角形等,它们影响估计的平滑程度。 3. 设置带宽(Bandwidth):控制核...
下面将详细介绍其中几个关键模块的功能: ##### 1. MEDCAD模块 MEDCAD模块作为医学影像数据与CAD之间的桥梁,提供了强大的双向交互能力,使得扫描数据与CAD数据之间的转换变得简单高效。具体来说: - **轮廓线...
在这个项目中,我们可以期待学习到以下几个与Python和软件开发相关的知识点: 1. **面向对象编程(Object-Oriented Programming, OOP)**:披萨店和披萨本身都是现实世界中的对象,很可能会被抽象成Python类。通过...
在MATLAB环境中,实现Wigner-Ville分布通常涉及以下几个步骤: 1. **信号预处理**:首先,你需要有一个实验数据集。这些数据可能来自于传感器测量、音频信号、图像处理或其他任何需要分析的信号源。确保数据是连续...
- **使用C#、Java、JavaScript、Objective-C、PHP、Python、Ruby和Visual Basic编写Ice应用**:同样地,也为其他几种语言提供了创建简单Ice应用的指南。 ### Slice语言详解 - **Slice编译**:介绍如何将Slice源...
在实现过程中,需要注意以下几个关键点: 1. 数据预处理:确保数据集是干净且无缺失值的。 2. 参数选择:核函数的带宽(或称为窗宽)对结果有很大影响。带宽太小可能导致过度拟合,而带宽太大则可能使细节丢失。通常...
- 使用了之前训练caffenet的脚本,说明了几个关键的参数设置。--resize_height和--resize_width参数用于调整图像大小,而--shuffle参数用于打乱数据集中的数据顺序,确保在训练过程中样本的随机性。文档中提到,...
字符串截取通常涉及到以下几个关键知识点: 1. **字符串类型**:在Delphi中,字符串通常使用`string`类型表示,这是一个动态的Unicode字符串类型。它可以在运行时自动调整长度,非常灵活。 2. **Substring函数**:...
在“医学图像处理DICOMM文件显示”这个主题中,主要涉及到以下几个关键知识点: 1. **DICOM 文件结构**:DICOM 文件由一系列的数据元素(Data Elements)组成,每个元素包含一个标签(Tag)和相关数据。标签定义了...
总结起来,Vue.js实现表格分页功能主要涉及以下几个步骤: 1. 使用`el-table`组件展示数据,并利用`slice`方法按需加载当前页数据。 2. 使用`el-pagination`组件创建分页导航,并监听`current-change`和`size-change...
在测试过程中,我们需要关注以下几个关键点: 1. **兼容性测试**:确保文件上传功能在各种浏览器和设备上都能正常工作,包括Chrome、Firefox、Safari、Edge以及移动设备。 2. **错误处理**:编写健壮的错误处理...
这种方法不仅可以统计字符出现的次数,还可以根据字符出现的次数进行排序,并仅显示出现次数最多的前几个字符。步骤如下: 1. **定义类**:定义一个`Summary`类,包含两个属性`char`和`count`,分别表示字符及其...
### Django 1.0 Cheat Sheet 知识点详解 #### 概述 "Django 1.0 Cheat Sheet" 是一份非常实用的参考资料,为开发者提供了关于 Django 1.0 版本中的各种模板标签和过滤器的快速查阅指南。这份文档涵盖了从基本的文本...