字符方法——字符方法示例:更改字符串2

未匹配的标注

已经看到:因为字符串不可变,不能被直接就地修改。从2.6,3.0和之后的版本,bytearray支持就地文本修改,但只适用于简单的8比特类型。之前探索了文本字符串的修改,但这里在字符串方法的背景下第二次快速看一下。

一般要从现成的字符串创建新的文本值,可以使用如切片和连接等操作来构建新字符串。比如,在字符串中间替换两个字符,可以使用如下代码:

>>> S = 'spammy'
>>> S = S[:3] + 'xx' + S[5:] # 从S切割连续区间
>>> S
'spaxxy'

但是,如果你真的想替换一个子字符串,可以使用字符串replace方法来代替:

>>> S = 'spammy'
>>> S = S.replace('mm', 'xx') # 用xx替换S中所有的mm
>>> S
'spaxxy'

replace方法比这个代码暗示的更加通用。它将原来的子串(任何长度)和要用它替换的字符串(任何长度)作为参数,然后执行全局搜索和替换:

>>> 'aa$bb$cc$dd'.replace('$', 'SPAM')
'aaSPAMbbSPAMccSPAMdd'

在这样的角色中,replace可用作实现模板替换(比如:在表单信件中)的工具。注意这次我们简单地打印了结果,而非将其分配给名称——只有想保存备用时才需要将结果分配给名称。

如果需要替换出现在任何偏移量的一个固定尺寸字符串,可以再替换一次,或用字符串find方法搜索子串然后切片:

>>> S = 'xxxxSPAMxxxxSPAMxxxx'
>>> where = S.find('SPAM') # 搜索位置
>>> where # 出现在偏移量4
4
>>> S = S[:where] + 'EGGS' + S[(where+4):]
>>> S
'xxxxEGGSxxxxSPAMxxxx'

find方法返回了子串出现的偏移量(默认从前面搜索),如果未找到则返回-1。如之前看到的:find是一个像in表达式的子串搜索操作,但find返回定位子串的位置。

另一个选项是使用replace带第三参数来限制为一次替换:

>>> S = 'xxxxSPAMxxxxSPAMxxxx'
>>> S.replace('SPAM', 'EGGS') # 替换所有
'xxxxEGGSxxxxEGGSxxxx'
>>> S.replace('SPAM', 'EGGS', 1) # 替换1次
'xxxxEGGSxxxxSPAMxxxx'

注意 replace 每次返回一个新的字符串对象。因为字符串不可变,方法从未真正就地改变原字符串,即使它们被称作“替换”!

连接操作和replace 方法在每次运行时产生新字符串对象的这个事实其实是使用它们来修改字符串的一个潜在缺点。如果必须对一个非常大的字符串进行非常多修改,可以通过转换字符串为支持就地修改的对象来提高脚本的性能:

>>> S = 'spammy'
>>> L = list(S)
>>> L
['s', 'p', 'a', 'm', 'm', 'y']

内置list函数(一个对象构建函数)从任何序列的项中构建出一个新的列表——在本例中,将字符串字符打散到列表中。一旦字符串在这种形式下,就可以对它进行多个修改而无需为每次修改产生新的对象拷贝:

>>> L[3] = 'x' # 适用于列表,而非字符串
>>> L[4] = 'x'
>>> L
['s', 'p', 'a', 'x', 'x', 'y']

在修改后,如果需要转换为字符串(比如:写入文件),使用字符串join方法来将列表连接回字符串:

>>> S = ''.join(L)
>>> S
'spaxxy'

join方法可能咋一看上去有点反直觉。因为它是字符串的一个方法(而非列表的),它通过想要的分隔符被调用。join将列表(或其他可迭代的类型)中的字符串连接起来(在列表项之间使用分隔符);在本例中,它使用了一个空字符串分隔符来将列表转换回字符串。更通用地,任何字符串分隔符和字符串组成的可迭代类型都可以:

>>> 'SPAM'.join(['eggs', 'sausage', 'ham', 'toast'])
'eggsSPAMsausageSPAMhamSPAMtoast'

事实上,一次性连接所有子串可能通常比单独连接它们要更快。确保还学习了从Python3.0和2.6开始就可用的可变bytearray字符串的之前的笔记(在第37章中有完整描述);因为它可以就地更改,所以它为必须被经常修改的一些8比特文本提供了这个list/join结合的可选方案。

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~