吃透Python-第 6 章 字符串

吃透Python-第 6 章 字符串

从第 1 章开始我们就一直在使用 str 型的字符串。本章,我们将继续学习字符串,以熟练掌握其用法。

字符串和 str 型
字符串的元素
索引运算符 [] 和索引表达式
分片运算符 [:] 和分片表达式
使用 len 函数获取字符串的长度(元素总数)
遍历字符串
可迭代对象
enumerate 函数
线性搜索字符串中的字符
判断字符串的大小关系和等价性
判断字符串是否相同
成员运算符(运算符 in 和运算符 not in)
find 方法和 rfind 方法
index 方法和 rindex 方法
拼接字符串和分割字符串
join 方法
替换字符串和删除字符串
字符串的格式化(运算符 %format 方法和 f 字符串)

6-1 字符串的基础知识

从第 1 章开始我们就一直在使用 str 型的字符串。本章,我们将继续学习字符串,以熟练掌握其用法。

字符串
  关于字符串,我们学习了以下内容。

字符串的类型是 str 型。
字符串由一系列字符组成,字符串字面量用于表示字符序列。
如何使用加法运算符 + 拼接字符串,以及如何使用乘法运算符 * 重复字符串。
如何在屏幕上输出字符串,以及如何从键盘读取字符串。
如何将字符串转换为整数和实数,以及如何将整数和实数转换为字符串。
如何在字符串中插入格式化的整数或实数。
没有字符的空字符串,其逻辑值为 False。
字符串的值不能改变,即字符串是不可变类型。
▶ 许多编程语言会将单一字符作为字符,将任意数量的字符排列在一起所形成的内容作为字符串进行区分。Python 则没有区分字符和字符串,单一字符会被当作只有 1 个字符的字符串处理。

元素和索引
  本节,我们将继续学习字符串,熟练掌握其用法。

首先,思考字符串 ‘ABCDEFG’。因为字符串由一系列字符组成,所以如图 6-1 所示,7 个字符会按顺序连续排列。其中的一个个字符称为元素(element)。

在这里插入图片描述

图 6-1 字符串和两种索引

图中所示的小字整数是字符串的索引(index)。使用索引可以方便地取出字符串中的各个字符(元素)。字符串有以下两种索引。

非负数索引

从头开始按顺序排列为 0, 1, 2, …, ( 元素总数 -1)。

其索引值表示距第一个元素的偏移(offset),即位于第一个元素后的第几个元素。

负数索引

从末尾开始按顺序排列为 -1,-2,-3, …, (- 元素总数 )。

负数索引值是非负数索引值减去元素总数(本例中为 7)得到的值。另外,我们也可以把该值理解为 -( 从末尾开始的第几个元素 )。

不论哪一种索引值,都要插入索引运算符(index operator)“[]”中使用。索引表达式(subscription)的形式如下。

在这里插入图片描述

图 6-2 为索引表达式的一个示例。从头开始的第 3 个字符 ‘C’ 可以通过索引表达式 s[2] 或 s[-5] 进行访问(读写)。

在这里插入图片描述

图 6-2 索引运算符

现在我们使用索引运算符打印输出字符串内的所有字符。

代码清单 6-1 …该程序使用非负数索引 0~6 打印输出字符串内的所有字符。
代码清单 6-2 …该程序使用负数索引 -7~-1 打印输出字符串内的所有字符。
  仔细阅读上述程序后,我们就能大致理解索引运算符的使用方法了。

另外,指定了不合适的索引值(本例中为小于等于 -8 或大于等于 7 的数)会导致错误产生。

在这里插入图片描述

▶ 执行以下程序后,程序会发生错误(产生了 IndexError 异常,程序终止执行)。我们来通过以下程序进行确认。

chap06/list0601x.py…该程序在代码清单 6-1 的基础上添加了打印输出 s[7] 的代码。
chap06/list0602x.py…该程序在代码清单 6-2 的基础上添加了打印输出 s[-8] 的代码。

使用索引遍历字符串
  如果将字符数较多的字符串作为对象,或将任意字符数的字符串作为对象,那么针对所有元素逐一指定索引的方式(如前面介绍的程序所示)存在很大缺陷。

代码清单 6-3 通过 for 语句循环对程序进行了优化,并修改程序使其从键盘读取字符串。

在这里插入图片描述

首先来看蓝色底纹部分的 len( s)。len 函数是内置函数,传入字符串参数后,函数返回字符串的元素总数(字符总数)。具体如图 6-3 所示。

在这里插入图片描述

图 6-3 遍历字符串

len 这个名字来源于 length,表示长度。该函数不仅可以获取字符串的元素总数,还可以获取下一章介绍的列表的元素总数。

要点 使用 len 函数可以获取字符串(列表等)的元素总数。

在运行示例中,len(s) 等于 6。因此,for 语句中 i 的值会从 0 递增到 5,同时,程序输出“i 的值”和“s[i] 的值”。

索引 i 的值会从 0 递增到 5,即图中用蓝色圆底的数字 0 、1 等表示的值。

然后,s[i] 为索引对应的元素值,即 ‘A’、‘B’ 等。

▶ 也就是说,现在获取的字符是 s[i],其索引是 i。

屏幕按顺序显示 0 和 A,1 和 B 等。

请试着输入各种字符串。因为程序使用 len(s) 获取了字符串的长度,所以程序会从头到尾输出所有字符。

按顺序获取元素称为遍历。请记住这个基本的编程术语。

▶ 有多种方法可以让程序遍历字符串并打印输出字符串。请通过代码清单 6-8~代码清单 6-12 所示程序进行学习。

搜索字符串内的字符
  代码清单 6-4 是一个通过遍历字符串,搜索其中有无特定字符,并在有特定字符的情况下输出字符位置的程序。

在这里插入图片描述

与前面相同,在此运行示例中,‘ABCDEF’ 读取到 s 中,所以 len(s) 的值等于 6。程序执行 for 语句后,i 的值从 0 递增到 5,同时,程序对字符串进行遍历。

搜索成功

在按顺序从头遍历字符串时,如果读取的字符 s[i] 与要查找的字符 c 相等,则搜索成功。

在运行示例 1 中,遍历过程如图 6-3 所示,从 a遍历到d 时, d 中的 s[i] 与变量 c(即 ‘D’)相等。搜索成功后,程序输出相应信息,然后执行 break 语句,强制结束 for 语句的运行。

搜索失败

如果 for 语句(程序没有执行 break 语句来强制结束)执行循环一直到最后,即遍历到 f 也没有查找到字符,就说明字符串 s 中没有要查找的字符 c。此时搜索失败,程序会输出相应的信息(运行示例2 )。

▶ 注意,程序末尾的 else 代码块属于 for 语句而不是 if 语句。

像该程序那样,以排列的元素为对象,从头开始按顺序逐个读取元素进行搜索的算法称为线性搜索(linear search)。大家也要牢记这个基础术语。

▶ 这里,我们学习了搜索方法。实际程序一般会使用运算符 in(第 136 页)和 find 方法(第 140 页)。

分片
  学习完索引,现在开始学习分片。分片指从字符串中取出连续的一部分字符或按一定周期取出一部分字符,生成新的字符串。分片有两种形式。

在这里插入图片描述

使用了分片运算符的分片表达式(slicing)在 [] 中需要插入一个或两个冒号。在分片表达式中指定的值含义如下。

开始 i   …相当于取出范围内的第一个元素的索引

 结束 j   …相当于取出范围内的最后一个元素的下一个元素的索引

 步进 k   …取字符的间隔

分片时取出的最后一个元素不是 s[j],而是 s[j] 之前的元素(专栏 6-1)。

另外,如果 k 为负数,分片时则反向取出字符。

现在我们通过示例进行确认。字母表的 26 个大写字母排列成字符串 s,程序分片取出 s 的字符。请参照右图进行学习。

在这里插入图片描述

在指定 i、j 和 k 时,需要遵循以下规则。

i 和 j 如果大于 len(s),则程序认为 i 和 j 等于 len(s)。

与索引不同,即使指定正常范围以外的值,程序也不会产生错误。

 

i 省略或为 None 时,程序认为 i 等于 0。

j 省略或为 None 时,程序认为 j 等于 len(s)

以上规则稍显复杂,但实际上,正因为有了这些规则,我们才可以轻松指定分片中的数字。我们来看几个例子。

所有元素

在取出所有元素时,使用分片表达式指定 i 为 0,j 为 len( s),即 s[0:26]。但是,分片表达式也可以使用只省略 j 的 s[0:] 表示,还可以使用 i 和 j 都省略的 s[:] 表示。

从某个元素开始到末尾

在取出从索引 i 的元素开始到末尾的元素时,需要使用省略了 j 的分片表达式 s[i:]。

最后 n 个元素

使用 s[-n:] 取出末尾的 n 个元素。

在省略 i、j 和 k 中的一个或多个的情况下,分片表达式的使用方法总结如下。

s[:] 所有字符 s[:] ‘ABCDEFGHIJKLMNOPQRSTUVWXYZ’
s[:n] 开头的 n 个元素 s[:5] ‘ABCDE’
s[i:] 从 s[i] 开始到字符串末尾 s[5:] ‘FGHIJKLMNOPQRSTUVWXYZ’
s[-n:] 最后 n 个元素 s[-5:] ‘VWXYZ’
s[::k] 每隔 k - 1 个元素取出一个元素 s[::3] ‘ADGJMPSVY’
s[::-1] 反向取出所有元素 s[::-1] ‘ZYXWVUTSRQPONMLKJIHGFEDCBA’

▶ 当 n 大于元素总数时,取出所有元素。

从下一章开始讲解的列表和元组也可以使用索引表达式和分片表达式。

字符串是不可变类型,它的值不能改变。因此,赋值时如果索引表达式或分片表达式在等号左边,程序就会产生错误(例 6-2)。

在这里插入图片描述

如果为了把 ‘F’ 修改为 ‘X’ 而对 s[5] 进行赋值,程序就会产生错误。

‘X’、到 ‘E’ 为止的分片,以及 ‘F’ 之后的分片可以正常进行拼接。

专栏 6-1 关于range和分片表达式中指定的值

  第 4 章介绍的 range(n)range(a, b) 所生成的排列式的最后一个值分别为 n-1 和 b-1,不包括实参指定的值 n 或 b 本身(即指定值的前一个值)。这里讲解的分片表达式 s[:n] 和 s[a:b] 同样如此。

  这种用法的好处如下所示。

n 和 b-a 能直接表示长度(元素总数)。
执行 range(a, b)range(b, c),或者 s[:n] 和 s[n:],可以没有重复、连续地列出元素。

使用比较运算符判断值的大小关系和等价性
  第 3 章介绍了比较运算符,它用来判断两个值的大小关系和等价性。<、<=、>、>=、== 和 != 这 6 个比较运算符都可用于字符串。

我们来看代码清单 6-5。

在这里插入图片描述

程序根据字符串中各个字符的字符编码来判断字符串的大小关系(专栏 6-2)。

另外,比较运算符可以连续使用,所以 ‘AAA’ <= s <= ‘ZZZ’ 或 s1 == s2 == ‘ABC’ 也能用来进行判断。

要点 使用比较运算符 <<=>>===!= 判断字符串的大小关系和等价性。

分别生成的字符串是不同的对象。因此,即使字符串中的所有字符都相同,在使用 is 运算符的情况下,判断结果也为假。

我们来看代码清单 6-6。

在这里插入图片描述

像运行示例那样,即使 s1 和 s2 读入相同的字符串 ‘ABC’,s1 和 s2 也不会被程序视为相同的字符串(此时 s1 的标识值和 s2 的标识值不同)。

要点 分别生成的字符串,即使所有字符都相同,也是拥有不同标识值的对象。

成员运算符 in
  我们可以调用表 6-1 中的成员运算符(membership test operator),即运算符 in 和运算符 not in 来查看某个字符串是否包含其他字符串。

表 6-1 成员运算符

在这里插入图片描述

▶ 如果 x 是空字符串,x in y 的结果一定是 True。另外,运算符 in 也能以 x in y in z 这种形式连续使用。比如,'A' in 'AB' in 'ABC' 的结果是 True

代码清单 6-7 利用上述运算符,判断某个字符串中是否包含其他字符串并输出判断结果。

在这里插入图片描述

利用运算符 in 可以判断字符串 txt 是否包含字符串 ptn。如果利用运算符 not in,则可以反过来进行判断(‘chap06/list0607a.py’)。

▶ 在 3-1 节中,我介绍了判断季节的示例程序,该程序对集合使用了运算符 in

运算符 in 是 Python 中一个重要的运算符,它可用于字符串、列表和集合。

在这里插入图片描述

专栏 6-2 判断字符串的大小关系和等价性

  在判断字符串的大小关系时,程序从第一个字符开始按顺序比较字符编码(第 195 页),如果编码值相同则比较下一个字符,如此循环。当然,如果某个字符编码更大,程序则会判断包含该字符的字符串更大

  以比较 'ABCD''ABCE' 为例,当比较到第 4 个字符时,程序会判断后一个字符串更大。另外,像 'ABCE 和 'ABCD' 这样,前 3 个字符相同,但其中一个字符串的字符数更多时,程序会判断字符数更多的字符串大

  运算符 == 和运算符 != 会针对所有字符判断等价性

使用 enumerate 函数遍历字符串
  Python 提供了 enumerate 函数对排列的元素进行遍历并获取索引的值和元素的值。代码清单 6-8 是代码清单 6-3 修改后的程序。

在这里插入图片描述

在本书中第一次出现的 enumerate 函数是一个内置函数,它可以成对获取索引和元素。enumerate 函数不仅适用于字符串,还可用于下一章讲解的列表。

在运行示例中,程序执行 for 语句后,会按照以下方式取出索引和元素。

1 次 … (0, 'A') 被成对地取出并赋给 (i, ch)2 次 … (1, 'B') 被成对地取出并赋给 (i, ch)

……

代码清单 6-3 所示程序通过 len 函数获取元素总数,而当前程序不需要使用 len 函数。

▶ 这里的“成对”对应于第 8 章讲解的元组。在 Python 中有许多情况会(显式或隐式地)用到元组。我会在第 8 章再次对该程序进行详细讲解。

计算机从 0 开始计数,而我们人在计数时一般从 1 开始。enumerate 函数可以指定第 2 个参数为计数的初始值,利用此特性从 1 开始计数的程序如代码清单 6-9 所示。

在这里插入图片描述

在运行示例中,程序从头开始按顺序取出字符,即 (1, ‘A’), (2, ‘B’) , …

现在运行代码清单 6-10 反向进行遍历。

在这里插入图片描述

reversed 函数是内置函数,它用于生成并返回给定序列的反向序列。reversed 函数不仅适用于字符串,还可用于下一章讲解的列表。

▶ Python 从 2.4 版本开始引入 reversed 函数。在 reversed(s) 被引入以前,程序使用 s[::-1] 生成反向序列(代码清单 6-12)。

不使用索引值遍历字符串
  在遍历字符串时,如果不使用索引值,程序就会变得更加简洁。具体如代码清单 6-11 和代码清单 6-12 所示。

在这里插入图片描述

第 4 章关于 for 语句介绍了以下内容。

for 变量 in 排列式 : 代码组”指在循环结束前的每一次循环过程中,取出排列式中的数字并将其赋给变量,然后执行代码组。

排列式的标准说法是可迭代对象(iterable object)。该对象可以从头开始按顺序逐一取出元素(第 232 页将对此进行详细讲解)。

因为字符串是可迭代对象,所以可以放在 for 语句的 in 之后。

在运行示例中,字符串 ‘ABCDEFG’ 是一个从 ‘A’ 排列到 ‘G’ 的可迭代对象。程序在执行循环时,每次都会从该可迭代对象中取出一个字符并将其赋给 ch。

在代码清单 6-12 中,程序将反向获取所有元素的分片表达式 s[::-1] 作为遍历对象。在运行示例中,程序从字符串 ‘GFEDCBA’ 中逐一取出字符输出。

当然,像代码清单 6-10 那样使用 reversed(s) 会得到相同的运行结果(chap06/list0612a.py)。

6-2 操作字符串

上一节的程序只是单纯使用了字符串字面量和赋给变量的字符串。现在我们继续学习字符串,熟练掌握字符串的使用方法。

搜索
  Python 提供了许多方法来判断某个字符串是否包含了其他字符串。

▶ 注意:如果没有用过其他编程语言,可以先跳过本节。在学习完第 7 章的列表、第 8 章的元组、第 9 章的函数和第 11 章的类之后再回来学习本节的内容。

使用成员运算符 in 和 not in 进行判断
  上一节介绍了使用运算符 in 和运算符 not in 判断某个字符串是否包含了其他字符串的方法。

使用 find 系列的方法进行判断
  在使用运算符 in 的情况下,虽然可以判断出字符串是否被包含,但我们无法得知被包含的字符串的位置。Python 提供了 find 方法、rfind 方法、index 方法和 rindex 方法来帮助我们查看被包含的字符串的位置。

在这里插入图片描述

如果字符串 str 在 [start: end] 的范围内包含 sub,则返回其中最小的索引值,否则返回 -1(参数 start 和参数 end 可以省略且与分片的指定方式相同)。

包围参数的标记 [ ] 用于说明其中的参数可以省略。

 在本方法中,接收的参数有 3 个,分别是 sub、start 和 end。在调用方法时,可以只省略第 3 个参数 end,也可以同时省略第 2 个参数 start 和第 3 个参数 end(第 1 个参数 sub 不能省略)。

在这里插入图片描述

如果字符串 str 在 [start:end] 的范围内包含 sub,则返回其中最大的索引值,否则返回 -1(参数 start 和参数 end 可以省略且与分片的指定方式相同)。

在这里插入图片描述

该方法与 find() 相同。但是,如果没有找到 sub,程序就会抛出 ValueError 异常。

在这里插入图片描述

该方法与 rfind() 相同。但是,如果没有找到 sub,程序就会抛出 ValueError 异常。

▶ 当字符串包含多个 sub 时,r 系列方法会返回被包含的字符串最后一次出现的位置。另外,我会在第 12 章对 index 和 rindex 抛出的异常进行介绍。

方法(method)是属于特定类型(类)的函数,我们可以使用以下形式对方法进行调用。

变量名.方法名 ( 实参的序列 )

这里的 () 是第 2 章介绍的调用运算符。

比如,在查看字符串 s1 中是否包含 ‘ABC’ 时需要调用 find 方法,这时用到的调用表达式为 s1.find(‘ABC’)。

我们可以把方法的调用理解为以下内容(图 6-4)。

字符串 s1,你的字符串中包含 'ABC' 吗?如果包含,请告诉我它首个字符出现的位置吧!

另外,向对象发送请求就是向对象发送消息。

▶ 关于发送消息,具体如下。

对象 s1 是字符串型(str 型),它拥有 find 方法。
向 s1 发送消息以执行 find 方法。
此时传递的实参'ABC'起到辅助指示的作用。
 我将在第 11 章对方法进行详细介绍。

代码清单 6-13 是使用 index 方法进行搜索的示例程序。

在这里插入图片描述

▶ 该程序使用了异常处理,大家可以在学完第 12 章后再来回顾该程序的内容。

在这里插入图片描述

图 6-4 调用方法

其他方法
  除了 find 系列的方法,Python 还提供了其他 3 种方法。

在这里插入图片描述

返回 sub 在字符串 str 的 [start:end] 这一范围内,不重叠出现的次数(参数 start 和参数 end 可以省略且与分片的指定方式相同)。

在这里插入图片描述

如果字符串以 prefix 开头则返回 True,否则返回 False。prefix 也可以使用元组,此时该方法用于判断字符串 str 是否以 preifx 元组中的某个字符串开头。如果指定 start,则从 start 的位置开始判断。如果指定 end,则比较到 end 的位置结束。start 和 end 都可以省略。

在这里插入图片描述

如果字符串以 suffix 结束则返回 True,否则返回 False。suffix 也可以使用元组,此时该方法用于判断字符串 str 是否以 suffix 元组中的某个字符串结束。如果指定 start,则从 start 的位置开始判断。如果指定 end,则比较到 end 的位置结束。start 和 end 都可以省略。

代码清单 6-14 调用了前面介绍的多个方法。

在这里插入图片描述

首先查看 txt 中包含的 ptn 的个数(赋值给变量 c)。程序根据 ptn 的个数进行了不同处理,具体如下所示。

不包含 ptn

打印输出相应的信息。

包含一个 ptn

使用 find 方法,打印输出 ptn 的位置。

包含多个 ptn

使用 find 方法和 rfind 方法查看并输出 ptn 首次和最后一次被包含的位置。

专栏 6-3 string模块提供的字符串

string 模块定义了以下字符串。

在这里插入图片描述

比如,Python用变量名 string.digits(string 是模块名,digits 是变量名)表示字符串 ‘0123456789’。

如果不了解 string 模块提供的这些字符串,编程时就需要自己定义类似的变量(应当避免如此)。

代码清单 6C-1 是一个使用了 string.ascii_lowercase 和 string.ascii_uppercase 的示例程序。该程序在读取一个字符后会查看该字符在字母表中的位置。

在这里插入图片描述

使用 import 声明指定 * 后,程序可以只用 ascii_lowercase 和 ascii_uppercase 来代替 string.ascii_lowercase 和 string.ascii_uppercase 访问相应的字符串(具体内容会在第 10 章介绍)。

如果 ascii_lowercase 包含输入的字符 c,则程序输出 c 在 ascii_lowercase 中的位置。如果不包含,则程序查看 ascii_uppercase 中是否包含 c,并在包含 c 的情况下输出 c 在 ascii_uppercase 中的位置。

第 13 章的代码清单 13-10(第 366 页)也应用了上述字符串。

拼接字符串
  Python 提供了许多方法来拼接和分割字符串。因为字符串是不可变类型,所以不论使用什么样的方法,程序都只能生成新的字符串而无法修改字符串本身。

要根据各个方法的优缺点和适用场景灵活运用各种方法。

通过增量赋值拼接字符串和重复字符串
  第 1 章介绍过使用加法运算符 + 可以拼接字符串,使用乘法运算符 * 可以重复字符串。

+= 和 *= 可以用来对字符串进行增量赋值。我们来看例 6-3。

在这里插入图片描述

▶ 第 1 章介绍了在字符串字面量之间插入空格、制表符和换行符等空白字符进行拼接的方法(例如,'ABC' 'DEF' 表示 'ABCDEF')。这是字符串字面量在字符上的拼接,并不是运算,所以该方法不适用于变量。
s1 = 'ABC'
s2 = 'XYZ'
s1 s2                # 无法拼接s1和s2

使用 join 方法拼接字符串
  多个字符串构成可迭代对象后,join 方法可以基于该对象中的字符串进行拼接并生成新的字符串。

str.join(iterable)

以 str 为分隔符,iterable 包含的字符串从头开始按顺序拼接后,join 方法返回拼接后的字符串。另外,如果 iterable 中存在非字符串的元素,程序则会抛出 TypeError 异常。

join 的使用形式如下。

分隔用字符串 .join( 存储待拼接字符串的可迭代对象 )

我们通过例 6-4 来进行确认。

在这里插入图片描述

在本例中,程序对元组中的字符串进行了拼接。当然,也可以对列表内的字符串进行拼接。

前面说过,字符串本身也是可迭代对象,因此我们也可以把字符串当作 join 方法的拼接对象(例 6-5)。

在这里插入图片描述

在本例中,程序逐一取出字符串中的各个字符进行拼接。join 方法可以用来在字符串的各个字符之间插入其他字符或字符串。

一般来说,使用 join 方法比使用运算符 + 或运算符 += 的拼接速度更快。

如果要对数字等非字符串构成的可迭代对象进行拼接,可以使用 7.2 节介绍的解析式。我们试着对列表进行拼接(例 6-6)。

在这里插入图片描述

程序使用 str 函数将各个元素转换为字符串后对其进行拼接。

专栏 6-4 使用f字符串拼接字符串

  下一节会介绍 f 字符串。f 字符串不仅可以用来拼接字符串,还可以轻松实现字符串与(数字等)非字符串之间的拼接(插入字符串)。代码清单 6C-2 是使用 f 字符串进行拼接的程序示例。

在这里插入图片描述

分割字符串
使用 split 方法分割字符串
  与 join 方法相反,split 方法用于分割字符串并生成列表。

str.split(sep=None, maxsplit=-1)

通过分隔用字符串 sep 分割字符串后,程序返回由分割后的字符串构成的列表。如果传递了参数 maxsplit,程序的最大分割次数就会被设定为 maxsplit(即生成的列表最多有 maxsplit+1 个元素)。如果没有传递参数 maxsplit,或者 maxsplit 设定为 -1,则程序不限制分割次数。

sep 可以设定为多个字符。另外,如果对象字符串包含连续的分隔符,程序就会在连续的分隔符位置分割出空字符串。此外,程序对空字符串进行分割时会返回 [‘’]。

如果没有设定 sep,或者当 sep 为 None 时,程序会将连续的空白字符作为分隔符。另外,即使字符串的开头和末尾有空白字符,列表的首个元素和最后一个元素也不会是空字符串。因此,如果用 None 对空字符串或仅由空白字符构成的字符串进行分割,程序就会返回 []。

我们使用 split 方法来分割字符串(例 6-7)。

在这里插入图片描述

代码清单 6-15 是使用 split 方法的程序。该程序会读取键盘输入并以逗号区分两个字符串。

在这里插入图片描述

在运行示例中,程序以逗号 ‘,’ 为分隔符对读取的(input 函数返回的)字符串 ‘Fukuoka, Nagasaki’ 进行分割,结果得到包含两个元素的列表 [‘Fukuoka’, ‘Nagasaki’]。列表中的元素 ‘Fukuoka’ 和 ‘Nagasaki’ 按顺序赋给了 a 和 b。

▶ 除此以外,Python 还提供了以下几个分割字符串的方法。

 partition 方法…将字符串分割为分隔符左边的字符串、分隔符本身和分隔符右边的字符串这 3 部分。

splitlines 方法…以换行符为分隔符对字符串进行分割。

替换字符串
  replace 方法用于将字符串中包含的特定字符串替换为其他的字符串。

str. replace(old, new[, count])

复制字符串并将字符串 old 全部替换为 ne w,然后返回新的字符串。如果指定 count 参数,程序就会从前往后替换 count 次 old。count 参数也可以省略。

我们来试着替换字符串(例 6-8)。

在这里插入图片描述

删除字符串
  strip 方法可用于删除从文件读取的字符串末尾的换行符。

str.strip([chars])

从字符串的头尾删除 chars 指定的字符并返回新字符串。如果 chars 省略或为 None,则删除字符串中的空格。

我们来使用 strip 方法删除字符串中的字符(例 6-9)。

在这里插入图片描述

▶ 除此之外,Python 还提供了 lstrip 方法和 rstrip 方法。
专栏 6-5 调试和注释代码

  程序的缺陷和错误称为 bug,寻找 bug 并分析其成因的过程称为调试(debug)。

  在调试程序时,编程人员会对程序进行各种测试和修正。这时,如果删除了程序正确的部分,程序就很难恢复原样了。

  在这种情况下比较常用的是注释代码的方法,即在程序代码(而非注释)部分的开头插入。

  但是,程序读者无法分辨注释的目的,不知道注释的部分已经没有用了还是要用于测试,这就容易造成误解。

  注释代码说到底只能作为一种临时方法使用。

其他方法
  除了上文介绍的方法,Python 还提供了其他处理字符串的方法。我们来尝试使用一下其中的几个方法。

大写字母和小写字母之间的转换

对字符串进行大写字母和小写字母的转换。

str.capitalize()

将字符串的首字符转换为大写字母,其余字符转换为小写字母,然后复制并返回新的字符串。

str.lower()

将字符串中存在大小写区别的字母全部转换为小写字母,然后复制并返回新的字符串。

str.swapcase()

将字符串中的大写字母转换为小写字母,小写字母转换为大写字母,然后复制并返回新的字符串。

str.title()

将字符串中的首字母转换为大写字母,其余存在大小写区别的字母转换为小写字母,然后复制并返回新的字符串。

str.upper()

将字符串中存在大小写区别的字母全部转换为大写字母,然后复制并返回新的字符串。

我们来使用这些方法对字符串进行转换(例 6-10)。

在这里插入图片描述

判断字符类别

表 6-2 所示方法用于对字符串中的所有字符进行判别,如果字符串属于特定的类别则返回 True,否则返回 False(例 6-11)。

在这里插入图片描述

表 6-2 判断字符类别的方法

在这里插入图片描述

对齐字符串

根据指定长度分别生成原字符串左对齐、居中、右对齐的字符串。

str.center(width[, fillchar])

返回一个居中且使用 fillchar(省略时用空格)填充至长度 width 的新字符串。当 width 小于等于 len(s) 时返回原字符串。

str.ljust(width[, fillchar])

返回一个左对齐且使用 fillchar(省略时用空格)填充至长度 width 的新字符串。当 width 小于等于 len(s) 时返回原字符串。

str.rjust(width[, fillchar])

返回一个右对齐且使用 fillchar(省略时用空格)填充至长度 width 的新字符串。当 width 小于等于 len(s) 时返回原字符串。

我们可以通过例 6-12 确认以上 3 个方法的运行过程。

在这里插入图片描述

在示例程序中,‘ABC’ 始终被填入到长 20 个字符的字符串中。

▶ Python 提供了内置函数(而非方法)对字符和字符编码进行转换。

chr 函数

chr(i) 返回一个字符串,该字符串由整数 i 对应的 Unicode 码字符构成。比如 chr(97) 返回字符串 'a'ord 函数

该函数以单个 Unicode 字符构成的字符串作为实参。函数被调用后返回一个整数,该整数表示实参中字符的 Unicode 编码。比如 ord('a') 会返回整数 97

6-3 格式化

在往屏幕上或文件中输出数字或字符串时,必须进行格式化处理,指定基数或位数。我们来学习格式化的方法。

使用格式化运算符 %
  格式化操作的原则是生成一个新的字符串,该字符串在原字符串的基础上(根据需要指定基数和位数)插入了其他字符串或数字。

首先介绍使用格式化运算符(formatting operator)% 实现格式化操作的方法。该方法功能较少且使用范围有限,现已不被推荐使用了。不过由于许多既有程序仍用到了该方法,所以我们还是要加以学习,以便理解程序。

代码清单 6-16 所示程序使用该方法生成并输出格式化的字符串。

在这里插入图片描述

▶ 程序 chap06/list0616a.py 将上面的程序修改为从键盘读取各变量的值。

用于生成字符串的表达式如下所示。

字符串 % 值的序列               ※ 字符串中包含了格式说明。
▶ 当运算符 % 的左操作数是字符串时,程序将运算符 % 作为格式化运算符使用而不进行除法运算。我们可以针对不同类型(类)的运算对象定义不同的运算符行为(第 333 页)。

表 6-3 的转换说明(conversion specification)在左操作数字符串中的字符 % 后。表中橘色部分为标志位,蓝色部分为转换类型。

一般要在右操作数中放置与转换说明个数相同的值。在有多个值时使用 () 包围用逗号隔开的多个值。

表 6-3 主要的转换说明(格式化运算符)

在这里插入图片描述

图 6-5 演示了1 的转换过程。a、b 和 a + b 的值按照 %d 转换为十进制数插入字符串后,生成了新的字符串 ‘12 与 35 的和为 47。’。

另外,2 明确指示了转换说明和值的对应情况,值通过以下形式传递。

{‘名字1’: 值 1, ‘名字2’: 值 2, … }

在这里插入图片描述

图 6-5 使用格式化运算符 % 进行格式化操作

在转换说明中,名字以 ( 名字 ) 的形式放在 % 后。

▶ 排列的值用 () 包围后是元组,用 {} 包围后是字典(元组和字典将在第 8 章进行讲解)。

在转换说明中,以下内容按顺序排列(% 和转换类型之外的内容可以省略)。

% (名字) 标志位 最低字符数 精度 转换类型

最低字符数表示转换后至少有多少位(如果待转换的数字或字符串超过指定的位数,则输出数字的所有位数或整个字符串)。

精度表示浮点数的小数位数(默认为 6)。

我们来看一个示例(chap06/printf.py)。

在这里插入图片描述

使用 format 方法
  Python 从版本 2.6 开始针对 str 型引入了 format 方法。代码清单 2-14 演示了 format 方法的基础用法。

format 方法针对的是 {…} 形式的字符串,该字符串中包含了格式说明。

以下为转换多个值时的格式示例。

{} {} {}           各个值按顺序进行转换。

 {1} {2} {0}        指定值的位置(从前往后依次为 0, 1, …)。

 {kwd1} {kwd2} {kwd0}     指定值的关键字(名字)。

各格式的使用示例如下(chap06/format01.py)。

在这里插入图片描述

▶ 此外,我们可以使用 [] 指定位置,使用“.”指定属性。

表 6-4 总结了主要的格式说明。其基本用法是 {: 格式说明 },但是如果加上位置或关键字,用法就会变为 { 位置 : 格式说明 } 或 { 关键字 : 格式说明 }。

填充字符和对齐的格式说明
  在填充字符(fill character)后指定的是表 6-4 中橘色底纹部分的对齐(align)。另外,如果省略填充字符的格式说明,则填充字符默认为空格。

以下为位数(位数会在后面讲解)等于 12 的示例(chap06/format02.py)。

在这里插入图片描述

符号的格式说明
  表 6-4 中绿色底纹部分是符号(sign)的格式说明(chap06/format03.py)。

在这里插入图片描述

替代形式、位数、位分隔符和精度的格式说明
  在二进制数、八进制数或十六进制数前添加 0 的形式,以及没有小数部分的浮点数仍输出小数点的形式称为替代形式。替代形式要使用 # 进行指定。位数和精度的格式说明与运算符 % 基本相同。

另外,如果指定使用位分隔符“,”,则每 3 位数字会插入一个分隔符“,”。

表 6-4 主要的格式说明(format 方法)

在这里插入图片描述

转换类型的格式说明
  表 6-4 中的蓝色底纹部分为转换类型的格式说明。我们来指定整数型的基数或浮点型的输出形式。示例如下(chap06/format04.py)。

在这里插入图片描述

格式运算符 %、format 方法和 f 字符串的详细内容需要占用几十页的篇幅才能讲完,所以我这里只针对重要且基本的内容进行讲解。

大家可以通过 Python 的官方文档来学习各方法的详细用法。

使用格式化字符串字面量(f 字符串)
  与格式化字符串 % 相比,使用 format 方法进行格式化在功能方面更加多样,但缺点是代码过长。因此,Python 3.6 中引入了使用格式化字符串字面量,简称 f 字符串的格式化方法。

在使用该格式化方法时,要在字符串字面量前添加 f 或 F,以 f’…’ 或 F’…’ 的形式使用 f 字符串字面量。

该方法的最大优点是可以直接在 f 字符串中插入表达式。表达式的插入操作在 {} 中进行。在 f 字符串中,直接以 { 表达式 } 的形式编写待转换(待格式化)的表达式即可。

具体示例如下(chap06/fstring01.py)。

在这里插入图片描述

我们可以使用简洁而直观的方式编写代码。

▶ 花括号“{”和“}”可分别写为“{{”和“}}”。

另外,在 {} 中的表达式后可以添加冒号 : 和格式说明。f 字符串和 format 方法在格式说明的用法上基本相同。

代码清单 6-17 在使用 f 字符串进行各种格式化操作后生成并打印字符串。

格式化方法的选择
  上文讲解了 3 种格式化方法。如果在编程时不需要考虑与旧版本的兼容性,则应使用 f 字符串的方法。

▶ 为了让大家熟悉各种方法,这 3 种方法本书都使用了。

在这里插入图片描述

专栏 6-6 字符串的驻留机制

  我们知道内容相同的字符串如果不是一起生成的,就是不同的实体。sys.intern 函数可以开启字符串驻留机制,这样内容相同的字符串都会引用同一字符串实体。

代码清单 6-6 所示程序对字符串的同一性进行判断,如果在该程序中开启字符串驻留机制,则程序中内容相同的字符串都会引用同一字符串实体(chap06/intern.py)。

总结
字符串是 str 型的对象,其中每个字符都是字符串的元素。
字符串中的各个元素可以通过使用了索引运算符 [] 的索引表达式访问。在 [] 中指定索引值的方法如下图所示。

在这里插入图片描述

使用基于分片运算符 [:] 的分片表达式可以连续或按一定周期取出字符串的一部分作为新字符串。

在这里插入图片描述

字符串的元素总数(长度)可以通过 len 函数获得。

比较运算符可以判断字符串的大小关系和等价性。比较运算符以字符串内的字符编码(而非标识值)作为判断标准。
线性搜索是一种通过遍历字符串,从前往后按顺序逐一判断元素来查找目标值的算法。
用于判断归属性的运算符 in 和运算符 not in 可以用来查看字符串中是否包含了其他字符串。
使用 enumerate 函数可以在取出索引和元素(的元组)的同时遍历字符串。
字符串是可迭代对象,可以作为 for 语句中 in 的遍历对象。
方法是属于特定类型(类)的函数,以变量名 . 方法名 (…) 的形式调用。调用方法其实就是向对象发送消息。
使用 find 系列方法(find、rfind、index 和 rindex)可以查看字符串中是否包含其他字符串。
使用运算符 += 或 join 方法可以拼接字符串。
使用 split 方法可以分割字符串。
使用 replace 方法可以将字符串中的一部分内容替换为其他字符串。
使用 strip 方法可以从字符串中删除其他字符串中含有的字符。
string 模块定义了数字和字母等各种字符串。
Python 提供了多种格式化方法,包括格式化运算符 %、format 方法和格式化字符串字面量(f 字符串)。不论何种方法,都不会对字符串本身进行格式化,而是生成格式化后的新字符串。
注释程序的一部分代码是调试时使用的一个方法。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值