最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

python - Handling indentation in multiline f-string with multiline string variables - Stack Overflow

programmeradmin3浏览0评论

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
  • 1 I don't see why you'd expect a different result - there are eight spaces before Line one in blocks, and the shared whitespace that gets trimmed is four spaces. – jonrsharpe Commented Jan 19 at 13:09
  • I may trim four spaces by align block_a to the left, or dedent(block_a), but it still will not get the expected after a overall dedent. What I would like to have is when block_a after dedent, Line one should at the same level of Line three, and Line two four spaces indented. block_b is similar. – adamkwm Commented Jan 19 at 13:46
Add a comment  | 

2 Answers 2

Reset to default 1

To 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
发布评论

评论列表(0)

  1. 暂无评论