I know that we can use textwrap.dedent()
to handle indentation of a multiline string. But if it is a multiline f-string which includes replacement of multiline string variable, it becomes a little complicated.
The multiline strings in the following example are intentionally indented to simulate they are inside other structure:
from textwrap import dedent
block_a = """\
Line one
Line two"""
block_b = """\
Line four
Line five"""
blocks = f"""\
{block_a}
Line three
{block_b}"""
print(dedent(blocks))
What I want is:
Line one
Line two
Line three
Line four
Line five
Dedenting just blocks
is clearly not enough, the result is:
Line one
Line two
Line three
Line four
Line five
But dedenting also block_a
and block_b
does not help much,
blocks = f"""\
{dedent(block_a)}
Line three
{dedent(block_b)}"""
print(dedent(blocks))
and the result becomes:
Line one
Line two
Line three
Line four
Line five
What I really want is those replaced strings should have the same indentation level where I put the replacement field, while keeping their internal indentation in the variable. Then, I can perform a overall dedent to get the expected result.
Before the overall dedent, in the above case, what I want is:
Line one
Line two
Line three
Line four
Line five
It should still be the case if both replacement fields and Line three
indented four spaces more,
blocks = f"""\
{dedent(block_a)}
Line three
{dedent(block_b)}"""
what I want is:
Line one
Line two
Line three
Line four
Line five
I have a workaround using a format string instead of f-string,
blocks = """\
{}
Line three
{}"""
print(dedent(blocks).format(dedent(block_a), dedent(block_b)))
but I am still interested to know if I can do this by f-string, and any other methods that are useful in handling indentation in this case.
I know that we can use textwrap.dedent()
to handle indentation of a multiline string. But if it is a multiline f-string which includes replacement of multiline string variable, it becomes a little complicated.
The multiline strings in the following example are intentionally indented to simulate they are inside other structure:
from textwrap import dedent
block_a = """\
Line one
Line two"""
block_b = """\
Line four
Line five"""
blocks = f"""\
{block_a}
Line three
{block_b}"""
print(dedent(blocks))
What I want is:
Line one
Line two
Line three
Line four
Line five
Dedenting just blocks
is clearly not enough, the result is:
Line one
Line two
Line three
Line four
Line five
But dedenting also block_a
and block_b
does not help much,
blocks = f"""\
{dedent(block_a)}
Line three
{dedent(block_b)}"""
print(dedent(blocks))
and the result becomes:
Line one
Line two
Line three
Line four
Line five
What I really want is those replaced strings should have the same indentation level where I put the replacement field, while keeping their internal indentation in the variable. Then, I can perform a overall dedent to get the expected result.
Before the overall dedent, in the above case, what I want is:
Line one
Line two
Line three
Line four
Line five
It should still be the case if both replacement fields and Line three
indented four spaces more,
blocks = f"""\
{dedent(block_a)}
Line three
{dedent(block_b)}"""
what I want is:
Line one
Line two
Line three
Line four
Line five
I have a workaround using a format string instead of f-string,
blocks = """\
{}
Line three
{}"""
print(dedent(blocks).format(dedent(block_a), dedent(block_b)))
but I am still interested to know if I can do this by f-string, and any other methods that are useful in handling indentation in this case.
Share Improve this question edited Jan 20 at 3:21 adamkwm asked Jan 19 at 12:49 adamkwmadamkwm 1,1732 gold badges8 silver badges18 bronze badges 2 |2 Answers
Reset to default 1To get the result you are expecting, you would have to insert blocks a and b without additional indentation:
blocks = f"""\
{block_a}
Line three
{block_b}"""
This of course will look ugly when the code is inside other structures.
Alternatively, construct it all with variables:
middle_block = """\
Line three"""
blocks = f"{block_a}\n{middle_block}\n{block_b}"
But the important thing to remember is that, however you choose to build blocks
, it has to look like the output you want with additional indentation.
I think this will help you: \t and \n in f-strings
Use \t for indentation and \n for new lines in f-strings
text = "Line one \n\tLine two \nLine three \n\tLine four \nLine five"
print(text)
Line one
Line two
Line three
Line four
Line five
Line one
inblocks
, and the shared whitespace that gets trimmed is four spaces. – jonrsharpe Commented Jan 19 at 13:09block_a
to the left, ordedent(block_a)
, but it still will not get the expected after a overall dedent. What I would like to have is whenblock_a
after dedent,Line one
should at the same level ofLine three
, andLine two
four spaces indented.block_b
is similar. – adamkwm Commented Jan 19 at 13:46