The bare replacement mentioned by @ steven-rumbalski will be the most efficient way to accomplish this, but this is not the only way.
Here's another solution using lists. If the text has already been split into a list of lines, it will be much faster than running join() , replace() and 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)
The list can be changed in place, but there is a significant cost of execution compared to using the second variable. It is also moderately faster to deflect all lines and then swap the first line in another operation.
There is also a textwrap module. I disagree that using textwrap for indentation is non-pythonic. If the lines are combined into one line containing the lines of a new line, this line is essentially wrapped. Indentation is a logical extension of text wrapping, so textwrap makes sense to me.
Except that he is slow. Really, really slow. Like 15 times slower.
Python 3 added indent to textwrap , which makes indentation without textwrap very easy. Of course, a more elegant way to handle a lambda predicate, but that does exactly what the original question asked.
indented = textwrap.indent(text, ' ', lambda x: not text.splitlines()[0] in x )
Here are some timeit results from various methods.
>>> timeit.timeit(r"text.replace('\n', '\n ')", setup='text = """%s"""' % text) 0.5123521030182019
Two solutions for understanding the list:
>>> 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
And here is the unsuccessful result of textwrap :
>>> timeit.timeit(r"textwrap.indent(text, ' ', lambda x: not text.splitlines()[0] in x )", setup='import textwrap; text = """%s"""' % text) 7.7950868209591135
I thought that part of this time could be a terribly inefficient predicate, but even with the remote textwrap.indent still more than 8 times slower than a bare replacement.
>>> timeit.timeit(r"textwrap.indent(text, ' ')", setup='import textwrap; text = """%s"""' % text) 4.266149697010405