@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 进行缩进是 unpythonic 的。如果这些行连接在一个包含换行符的字符串中,则该字符串本质上是换行的。缩进是文本换行的逻辑扩展,所以 textwrap 对我来说很有意义。
除了它很慢。真的,真的很慢。就像慢了 15 倍。
indent
添加的Python 3textwrap
使得无需重新包装的缩进变得非常容易。当然有一种更优雅的方式来处理 lambda 谓词,但这正是原始问题所要求的。
indented = textwrap.indent(text, ' ', lambda x: not text.splitlines()[0] in x )
timeit
以下是各种方法的一些结果。
>>> 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
这是不幸的textwrap
结果:
>>> 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