保留缩进的三引号字符串

时间:2019-07-24 03:35:51

标签: python python-3.x indentation f-string

我正在尝试在Python3(.7)中使用三引号引起来的字符串来构建一些格式化的字符串。

我有一个内部字符串列表,所有这些都需要在以下选项卡中列出:

    This is some text
    across multiple
    lines.

还有一个应该包含内部字符串的字符串

data{
    // string goes here
}

创建内部字符串时,我无法使用制表符。因此,我的想法是将dedent与Python3三引号fstrings一起使用:

import textwrap

inner_str = textwrap.dedent(
    '''\
    This is some text
    across multiple
    lines.'''
)

full_str = textwrap.dedent(
    f'''\
    data{{
        // This should all be tabbed
        {inner_str}
    }}'''
)

print(full_str)

但是,缩进不保留:

    data{
        // This should all be tabbed
        This is some text
across multiple
lines.
    }

所需结果:

data{
    // This should all be tabbed
    This is some text
    across multiple
    lines.
}

如何在不预先标记内部字符串的情况下保留fstring的缩进?

3 个答案:

答案 0 :(得分:0)

已进行编辑,以避免使用制表符inner_str

import textwrap

line_tab = '\n\t'

inner_str = f'''\
This is some text
across multiple
lines.
'''

full_str = textwrap.dedent(f'''\
data{{
    // This should all be tabbed 
    {line_tab.join(inner_str.splitlines())}
}}'''
                           )

print(full_str)

输出:

data{
    // This should all be tabbed 
    This is some text
    across multiple
    lines.
}

答案 1 :(得分:0)

这似乎可以提供您想要的东西。

import textwrap

inner_str = textwrap.dedent(
    '''\
    This is some text
    across multiple
    lines.'''
)

full_str = textwrap.dedent(
    f'''
    data{{
{textwrap.indent(inner_str, "        ")}
    }}'''
)

更好的解决方案:

idt = str.maketrans({'\n': "\n        "})
print(textwrap.dedent(
    f'''
    data{{
        {inner_str.translate(idt)}
    }}'''
))

具有自定义标签宽度的另一种解决方案:

def indent_inner(inner_str, indent):
    return inner_str.replace('\n', '\n' + indent)   # os.linesep could be used if the function is needed across different OSs

print(textwrap.dedent(
    f'''
    data{{
        {indent_inner(inner_str, "        ")}
    }}'''
))

答案 2 :(得分:0)

这里没有一个答案似乎可以满足我的要求,因此我在用自己的解决方案来回答自己的问题,该解决方案与我所寻找的尽可能接近。不需要预先制表数据以定义其缩进级别,也不需要不缩进行(这会破坏可读性)。而是在使用时传递fstring中的当前行 的缩进级别。

并不完美,但是可以。

import textwrap


def code_indent(text, tab_sz, tab_chr=' '):
    def indented_lines():
        for i, line in enumerate(text.splitlines(True)):
            yield (
                tab_chr * tab_sz + line if line.strip() else line
            ) if i else line
    return ''.join(indented_lines())


inner_str = textwrap.dedent(
    '''\
    This is some text
    across multiple
    lines.'''
)


full_str = textwrap.dedent(
    f'''
    data{{
        {code_indent(inner_str, 8)}
    }}'''
)

print(full_str)
相关问题