资讯专栏INFORMATION COLUMN

Python实用技法第33篇:字符串连接及合并

JayChen / 2317人阅读

摘要:上一篇文章实用技法第篇对齐文本字符串下一篇文章问题我们想将许多小字符串合并成一个大的字符串。示例如下对于不必要的字符串连接操作也要引起重视。有时候在技术上并非必需的时候,程序员们也会忘乎所以地使用字符串连接操作。

上一篇文章: Python实用技法第32篇:对齐文本字符串
下一篇文章:
 问题

我们想将许多小字符串合并成一个大的字符串。

 解决方案

如果想要合并的字符串在一个序列或可迭代对象中,那么将它们合并起来的最快方法就是使用join()方法。示例如下:

>>> parts = ["Is", "Chicago", "Not", "Chicago?"]
>>> " ".join(parts)
"Is Chicago Not Chicago?"
>>> ",".join(parts)
"Is,Chicago,Not,Chicago?"
>>> "".join(parts)
"IsChicagoNotChicago?"
>>>

初看上去语法可能显得有些怪异,但是join()操作其实是字符串对象的一个方法。这么设计的部分原因是因为想要合并在一起的对象可能来自于各种不同的数据序列,比如列表、元组、字典、文件、集合或生成器,如果多带带在每一种序列对象中实现一个join()方法就显得太冗余了。因此只需要指定想要的分隔字符串,然后在字符串对象上使用join()方法将文本片段粘合在一起就可以了。

如果只是想连接一些字符串,一般使用+操作符就足够完成任务了:

>>> a = "Is Chicago"
>>> b = "Not Chicago?"
>>> a + " " + b
"Is Chicago Not Chicago?"
>>>

针对更加复杂的字符串格式化操作,+操作符同样可以作为format()的替代,很好地完成任务:

>>> print("{} {}".format(a,b))
Is Chicago Not Chicago?
>>> print(a + " " + b)
Is Chicago Not Chicago?
>>>

如果打算在源代码中将字符串字面值合并在一起,可以简单地将它们排列在一起,中间不加+操作符。示例如下:

>>> a = "Hello" "World"
>>> a
"HelloWorld"
>>>
 讨论

字符串连接这个主题可能看起来还没有高级到要用一整节的篇幅来讲解,但是程序员常常会在这个问题上做出错误的编程选择,使得他们的代码性能受到影响。

最重要的一点是要意识到使用+操作符做大量的字符串连接是非常低效的,原因是由于内存拷贝和垃圾收集产生的影响。特别是你绝不会想写出这样的字符串连接代码:

s = ""
for p in parts:
    s += p

这种做法比使用join()方法要慢上许多。主要是因为每个+=操作都会创建一个新的字符串对象。我们最好先收集所有要连接的部分,最后再一次将它们连接起来。

一个相关的技巧(很漂亮的技巧)是利用生成器表达式(见1.19节)在将数据转换为字符串的同时完成连接操作。示例如下:

>>> data = ["ACME", 50, 91.1]
>>> ",".join(str(d) for d in data)
"ACME,50,91.1"
>>>

对于不必要的字符串连接操作也要引起重视。有时候在技术上并非必需的时候,程序员们也会忘乎所以地使用字符串连接操作。例如在打印的时候:

print(a + ":" + b + ":" + c)     # Ugly
print(":".join([a, b, c]))       # Still ugly
print(a, b, c, sep=":")          # Better

将字符串连接同I/O操作混合起来的时候需要对应用做仔细的分析。例如,考虑如下两段代码:

# Version 1 (string concatenation)
f.write(chunk1 + chunk2)
# Version 2 (separate I/O operations)
f.write(chunk1)
f.write(chunk2)

如果这两个字符串都很小,那么第一个版本的代码能带来更好的性能,这是因为执行一次I/O系统调用的固有开销就很高。另一方面,如果这两个字符串都很大,那么第二个版本的代码会更加高效。因为这里避免了创建大的临时结果,也没有对大块的内存进行拷贝。这里必须再次强调,你需要对自己的数据做分析,以此才能判定哪一种方法可以获得最好的性能。

最后但也是最重要的是,如果我们编写的代码要从许多短字符串中构建输出,则应该考虑编写生成器函数,通过yield关键字生成字符串片段。示例如下:

def sample():
    yield "Is"
    yield "Chicago"
    yield "Not"
    yield "Chicago?"

关于这种方法有一个有趣的事实,那就是它不会假设产生的片段要如何组合在一起。比如说可以用join()将它们简单的连接起来:

text = "".join(sample())

或者,也可以将这些片段重定向到I/O:

for part in sample():
    f.write(part)

又或者我们能以混合的方式将I/O操作智能化地结合在一起:

def combine(source, maxsize):
     parts = []
     size = 0
     for part in source:
         parts.append(part)
         size += len(part)
         if size > maxsize:
             yield "".join(parts)
             parts = []
             size = 0
    yield "".join(parts)

for part in combine(sample(), 32768):
    f.write(part)

关键在于这里的生成器函数并不需要知道精确的细节,它只是产生片段而已。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/44122.html

相关文章

  • Python实用技法32:对齐文本符串

    摘要:解决方案对于基本的字符串对齐要求,可以使用字符串的和方法。例如的好处之一是它并不是特定于字符串的。此外,可作用于任意类型的对象,比字符串的以及方法要更加通用。上一篇文章实用技法第篇文本过滤和清理下一篇文章实用技法第篇字符串连接及合并 上一篇文章:Python实用技法第31篇:文本过滤和清理下一篇文章:Python实用技法第33篇:字符串连接及合并  问题 我们需要以某种对齐方式将文本...

    leon 评论0 收藏0
  • Python实用技法19:将多个映射合并为单个映射

    摘要:上一篇文章实用技法第篇同时对数据做转换和换算下一篇文章实用技法第篇针对任意多的分隔符拆分字符串需求 上一篇文章:Python实用技法第18篇:同时对数据做转换和换算下一篇文章:Python实用技法第20篇:针对任意多的分隔符拆分字符串 1、需求

    jlanglang 评论0 收藏0
  • Python实用技法20:针对任意多的分隔符拆分符串

    摘要:上一篇文章实用技法第篇将多个映射合并为单个映射下一篇文章实用技法第篇在字符串的开头和结尾处做文本匹配需求 上一篇文章:Python实用技法第19篇:将多个映射合并为单个映射下一篇文章:Python实用技法第21篇:在字符串的开头和结尾处做文本匹配 1、需求

    AlexTuan 评论0 收藏0
  • Python实用技法18:同时对数据做转换和换算

    摘要:上一篇文章实用技法第篇将名称映射到序列的元素中下一篇文章实用技法第篇将多个映射合并为单个映射需求 上一篇文章:Python实用技法第17篇:将名称映射到序列的元素中下一篇文章: Python实用技法第19篇:将多个映射合并为单个映射 1、需求

    ThreeWords 评论0 收藏0
  • Python实用技法30:从符串中去掉不需要的字符

    摘要:上一篇文章实用技法第篇用正则表达式处理字符下一篇文章实用技法第篇文本过滤和清理问题我们想在字符串的开始结尾或中间去掉不需要的字符,比如说空格符。解决方案方法可用来从字符串的开始和结尾处去掉字符。 上一篇文章: Python实用技法第29篇:用正则表达式处理Unicode字符下一篇文章:Python实用技法第31篇:文本过滤和清理  问题 我们想在字符串的开始、结尾或中间去掉不需要的字...

    yck 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<