返回介绍

索引和分片

发布于 2024-01-29 22:24:17 字数 4074 浏览 0 评论 0 收藏 0

因为将字符串定义为字符的有序集合,所以我们能够通过其位置获得他们的元素。在Python中,字符串中的字符是通过索引(通过在字符串之后的方括号中提供所需要的元素的数字偏移量)提取的。你将获得在特定位置的一个字符的字符串。

就像在C语言中一样,Python偏移量是从0开始的,并比字符串的长度小1。与C语言不同,Python还支持类似在字符串中使用负偏移这样的方法从序列中获取元素。从技术上讲,一个负偏移与这个字符串的长度相加后得到这个字符串的正的偏移值。能够将负偏移看做是从结束处反向计数。下面的交互例子进行了说明。

第一行定义了有一个四个字符的字符串,并将其赋予变量名S。下一行用两种方法对其进行索引:S[0]获取了从最左边开始偏移量为0的元素(单字符的字符串's'),并且S[-2]获取了从尾部开始偏移量为2的元素[或等效的,在从头来算偏移量为(4+(-2))的元素]。偏移和分片的网格示意图如图7-1所示[1]

图 7-1 偏移和分片:位置偏移从左至右(偏移0为第一个元素),而负偏移是由末端右侧开始计算(偏移-1为最后一个元素)。这两种偏移均可以在索引及分片中作为所给出的位置

上边的例子中的最后一行对分片进行了演示,这是索引的一种通用形式,返回的是整个一部分,而不是一个单个的项。也许理解分片最好的办法就是将其看做解析(分析结构)的一种形式,特别是当你对字符串应用分片时——它让我们能够从一整个字符串中分离提取出一部分内容(子字符串)。分片可以用作提取部分数据,分离出前、后缀等场合。我们将会在本章稍后看到另一个分片用作解析的例子。

这里将解释分片是如何运作的。当使用一对以冒号分隔的偏移来索引字符串这样的序列对象时,Python将返回一个新的对象,其中包含了以这对偏移所标识的连续的内容。左边的偏移作为下边界(包含下边界在内),而右边的偏移作为上边界(不包含上边界在内)。Python将获取从下边界直到但不包括上边界的所有元素,并返回一个包含了所获取的元素的新的对象。如果被省略,上、下边界的默认值对应分别为0和分片的对象的长度。

例如,我们所看到的那个例子,S[1:3]提取出偏移为1和2的元素。也就是说,它抓取了第二个和第三个元素,并在偏移量为3的第四个元素前停止。接着,S[1:]得到了从第一个元素到上边界之间的所有元素,而上边界在未给出的情况下,默认值为字符串的长度。最后,S[:-1]获取了除了最后一个元素之外的所有元素——下边界默认为0,而-1对应最后一项,不包含在内。

这在一开始学习看起来有些令人困惑,但是一旦你掌握了诀窍以后索引和分片就成为了简单易用的强大工具。记住,如果你不确定分片的意义,可以交互地试验一下。在下一章,我将会介绍如何通过对一个分片(不像是字符串一样不可改变)进行赋值从而改变一个特定对象的一部分内容。下面概括一些细节以供参考:

·索引(S[i])获取特定偏移的元素:

—第一个元素的偏移为0。

—负偏移索引意味着从最后或右边反向进行计数。

—S[0]获取了第一个元素。

—S[-2]获取了倒数第二个元素(就像S[len(s)-2]一样)。

·分片(S[i:j])提取对应的部分作为一个序列:

—上边界并不包含在内。

—分片的边界默认为0和序列的长度,如果没有给出的话。

—S[1:3]获取了从偏移为1的元素,直到但不包括偏移为3的元素。

—S[1:]获取了从偏移为1直到末尾(偏移为序列长度)之间的元素。

—S[:3]获取了从偏移为0直到但是不包括偏移为3之间的元素。

—S[:-1]获取了从偏移为0直到但是不包括最后一个元素之间的元素。

—S[:]获取了从偏移0到末尾之间的元素,这有效地实现顶层S拷贝。

上面列出的最后一项成为了一个非常常见的技巧:它实现了一个完全的顶层的序列对象的拷贝——一个有相同值,但是是不同内存片区的对象(在第9章介绍更多关于拷贝的内容)。这对于像字符串这样的不可变对象并不是很有用,但对于可以在原地修改的对象来说却很实用,例如列表。

在下一章,将会看到通过偏移进行索引(方括号)的语法也可以通过键对字典进行索引;操作看起来很相似,但是却有着不同的解释。

扩展分片:第三个限制值

在Python2.3中,分片表达式增加了一个可选的第三个索引,用作步进(有时称为是stride)。步进添加到每个提取的元素的索引中。完整形式的分片现在变成了X[I:J:K],这表示“索引X对象中的元素,从偏移为I直到偏移为J-1,每隔K元素索引一次”。第三个限制——K,默认为1,这也就是通常在一个切片中从左至右提取每一个元素的原因。如果你定义了一个明确的值,那么能够使用第三个限制去跳过某些元素或反向排列它们的顺序。

例如,X[1:10:2]会取出X中,偏移值1~9之间,间隔了一个元素的元素,也就是收集偏移值1、3、5、7和9之处的元素。如同往常,第一和第二限制值默认为0以及序列的长度,所以,X[::2]会取出序列从头到尾、每隔一个元素的元素:

也可以使用负数作为步进。例如,分片表达式"hello"[::-1]返回一个新的字符串"olleh"——前两个参数默认值分别为0和序列的长度,就像之前一样,步进-1表示分片将会从右至左进行而不是通常的从左至右。因此,实际效果就是将序列进行反转:

通过一个负数步进,两个边界的意义实际上进行了反转。也就是说,分片S[5:1:-1]以反转的顺序获取从2到5的元素(结果是偏移为5、4、3和2的元素):

像这样使用三重限制的列表来跳过或者反序输出是很常见的情况,可以通过参看Python的标准库手册来获得更多细节(或者可以在交互模式下运行几个实例)。我们将会在本书稍后部分再次学习这种三重限制的分片,届时将与for循环配合使用。

在本书稍后,我们将看到分片等同于用一个分片对象进行索引,这对于那些试图两种操作都支持的类编写者来说,是一个重要的发现:

为什么要在意:分片

贯穿本书始末,经常会使用边栏(就像现在的情况一样)这样的形式,让你对正在介绍的语言特性有个直观的认识,了解其在真实的程序中的典型应用。因为在看到绝大多数的Python内容之前,你将不会遇到很多的真实应用场景,这些边栏中介绍的内容也许包含了许多尚未介绍的话题。不过你应该将这些内容看做是预览的途径,这样你就能够找到这些抽象的语言概念是如何在平常的编程任务中应用的。

例如,稍后你将会看到在一个系统命令行中启动Python程序时罗列出的参数,这使用了内置的sys模块中的argv属性:

通常,你只对跟随在程序名后边的参数感兴趣。这就是一个分片的典型应用:一个分片表达式能够返回除了第一项之外的所有元素的列表。这里,sys.argv[1:]返回所期待的列表['-a','-b','-c']。之后就能够不考虑最前边的程序名而只对这个列表进行处理。

分片也常常用作清理输入文件的内容。如果知道一行将会以行终止字符(\n换行字符标识)结束,你就能够通过一个简单的表达式,例如,line[:-1],把这行除去最后一个字符之外的所有内容提取出来(默认的左边界为0)。无论是以上哪种情况,分片都表现出了比底层语言的实现更明确直接的逻辑关系。

值得注意的是,为了去掉换行字符常常推荐采用line.rstrip方法,因为这个调用将会留下没有换行字符那行的最后一个字符,而这在一些文本编辑器工具中是很常见的。当你确定每一行都是通过换行字符终止时适宜使用分片。

[1]具有数学思维的读者有时会发现这里有些不对称:最左侧的元素的偏移为0,而最右侧的元素的偏移为-1。唉,在Python中是没有所谓-0这样的偏移啊。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文