由@steven-rumbalski提到的裸替换将是实现这一点的最有效方法,但它不是唯一的方法。
下面是另一个使用列表理解的解决方案。如果文本已经被拆分成一列行,那么这将比运行join()、replace()和splitlines()快得多text = """A very very very very very very very very very very very very very very very very
long mutiline
string"""
lines = text.splitlines()
indented = [' ' + l for l in lines]
indented[0] = lines[0]
indented = '\n'.join(indented)
这个列表可以在适当的地方进行修改,但是与使用第二个变量相比,它的性能成本很高。缩进所有行,然后在另一个操作中调出第一行的速度也略快一些。
还有textwrap模块。我不同意使用textwrap进行缩进是不符合语法的。如果这些行连接在一个包含换行符的字符串中,则该字符串将被固有地包装。缩进是文本包装的逻辑扩展,所以文本包装对我来说很有意义。
只是它很慢。真的,真的很慢。慢了15倍。
Python 3在textwrap中添加了indent,这使得不重新包装的缩进非常容易。处理lambda谓词肯定有一种更优雅的方法,但这正是最初问题所要求的。indented = textwrap.indent(text, ' ', lambda x: not text.splitlines()[0] in x )
下面是各种方法的一些结果。>>> timeit.timeit(r"text.replace('\n', '\n ')", setup='text = """%s"""' % text)
0.5123521030182019
两个列表理解解决方案:>>> timeit.timeit(r"indented = [' ' + i for i in lines]; indented[0] = lines[0]", setup='lines = """%s""".splitlines()' % text)
0.7037646849639714
>>> timeit.timeit(r"indented = [lines[0]] + [' ' + i for i in lines[1:]]", setup='lines = """%s""".splitlines()' % text)
1.0310905870283023
下面是不幸的结果:>>> timeit.timeit(r"textwrap.indent(text, ' ', lambda x: not text.splitlines()[0] in x )", setup='import textwrap; text = """%s"""' % text)
7.7950868209591135
我认为其中一些时间可能是非常低效的谓词,但是即使去掉了它,textwrap.indent仍然比一个裸替换慢8倍多。>>> timeit.timeit(r"textwrap.indent(text, ' ')", setup='import textwrap; text = """%s"""' % text)
4.266149697010405