Python多行字符串的正确缩进

时间:2010-03-23 23:35:28

标签: python string

函数中Python多行字符串的正确缩进是什么?

    def method():
        string = """line one
line two
line three"""

    def method():
        string = """line one
        line two
        line three"""

或其他什么?

在第一个例子中将字符串悬挂在函数外部看起来有点奇怪。

15 个答案:

答案 0 :(得分:424)

您可能希望与"""

对齐
def foo():
    string = """line one
             line two
             line three"""

由于换行符和空格都包含在字符串本身中,因此您必须对其进行后处理。如果您不想这样做并且您有大量文本,则可能需要将其单独存储在文本文件中。如果文本文件不适合您的应用程序并且您不想进行后期处理,我可能会使用

def foo():
    string = ("this is an "
              "implicitly joined "
              "string")

如果要对多行字符串进行后处理以修剪掉不需要的部分,则应考虑textwrap模块或PEP 257中提供的后处理文档字符串技术:

def trim(docstring):
    if not docstring:
        return ''
    # Convert tabs to spaces (following the normal Python rules)
    # and split into a list of lines:
    lines = docstring.expandtabs().splitlines()
    # Determine minimum indentation (first line doesn't count):
    indent = sys.maxint
    for line in lines[1:]:
        stripped = line.lstrip()
        if stripped:
            indent = min(indent, len(line) - len(stripped))
    # Remove indentation (first line is special):
    trimmed = [lines[0].strip()]
    if indent < sys.maxint:
        for line in lines[1:]:
            trimmed.append(line[indent:].rstrip())
    # Strip off trailing and leading blank lines:
    while trimmed and not trimmed[-1]:
        trimmed.pop()
    while trimmed and not trimmed[0]:
        trimmed.pop(0)
    # Return a single string:
    return '\n'.join(trimmed)

答案 1 :(得分:229)

textwrap.dedent功能允许您在源中以正确缩进开头,然后在使用前将其从文本中删除。

正如其他一些人所指出的那样,权衡这是对文字的额外函数调用;在决定将这些文字放在代码中的位置时,请考虑这一点。

import textwrap

def frobnicate(param):
    """ Frobnicate the scrognate param.

        The Weebly-Ruckford algorithm is employed to frobnicate
        the scrognate to within an inch of its life.

        """
    prepare_the_comfy_chair(param)
    log_message = textwrap.dedent("""\
            Prepare to frobnicate:
            Here it comes...
                Any moment now.
            And: Frobnicate!""")
    weebly(param, log_message)
    ruckford(param)

日志消息文字中的尾随\是为了确保换行符不在文字中;这样,文字不会以空行开头,而是从下一个完整行开始。

来自textwrap.dedent的返回值是字符串每行上所有常见的前导空格缩进的输入字符串。因此,上述log_message值将为:

Prepare to frobnicate:
Here it comes...
    Any moment now.
And: Frobnicate!

答案 2 :(得分:22)

其他答案中似乎缺少的一个选项(仅在纳克萨的评论中深入提及)如下:

def foo():
    string = ("line one\n"          # Add \n in the string
              "line two"  "\n"      # Add "\n" after the string
              "line three\n")

这将允许正确对齐,隐含地连接线,并且仍然保持线移位,对我来说,这也是我想要使用多行字符串的原因之一。

它不需要任何后处理,但您需要在任何您希望该行结束的给定位置手动添加\n。内联或后面的单独字符串。后者更容易复制粘贴。

答案 3 :(得分:22)

像这样使用inspect.cleandoc

def method():
    string = inspect.cleandoc("""
        line one
        line two
        line three""")

相对缩进将按预期保持。

  

注意:在其相关上下文中缩进逻辑代码块以澄清结构是一种很好的做法。例如。属于变量string的多行字符串。

答案 4 :(得分:17)

更多选择。在启用了pylab的Ipython中,dedent已经在命名空间中。我查了一下,它来自matplotlib。或者它可以导入:

from matplotlib.cbook import dedent

在文档中,它声明它比textwrap等效的快,并且在我的ipython测试中,我的快速测试平均快3倍。它还有一个好处,它丢弃任何前导空行,这使您可以灵活地构建字符串:

"""
line 1 of string
line 2 of string
"""

"""\
line 1 of string
line 2 of string
"""

"""line 1 of string
line 2 of string
"""

在这三个例子中使用matplotlib dedent将给出相同的明智结果。 textwrap dedent函数将在第一个示例中有一个前导空白行。

明显的缺点是textwrap在标准库中,而matplotlib是外部模块。

这里的一些权衡... dedent函数使得代码在字符串定义时更具可读性,但稍后需要处理以获得可用格式的字符串。在文档字符串中,很明显你应该使用正确的缩进,因为docstring的大多数用法都会进行必要的处理。

当我在我的代码中需要一个非长字符串时,我发现以下公认的丑陋代码,我让长字符串从封闭的缩进中删除。绝对是失败的“美丽胜过丑陋。”但是有人可能会认为它比狡猾的选择更简单,更明确。

def example():
    long_string = '''\
Lorem ipsum dolor sit amet, consectetur adipisicing
elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip.\
'''
    return long_string

print example()

答案 5 :(得分:5)

如果您想要快速简便的解决方案并且不用输入换行符,您可以选择列表,例如:

def func(*args, **kwargs):
    string = '\n'.join([
        'first line of very long string and',
        'second line of the same long thing and',
        'third line of ...',
        'and so on...',
        ])
    print(string)
    return

答案 6 :(得分:4)

我更喜欢

platforms = cl.get_platforms()
platforms[0].get_devices()
[<pyopencl.Device 'Intel(R) Core(TM) i5-4570S CPU @ 2.90GHz' on 'Intel(R) OpenCL' at 0x706ac40>]

    def method():
        string = \
"""\
line one
line two
line three\
"""

答案 7 :(得分:3)

我的两分钱,逃避行尾以获得缩进:

def foo():
    return "{}\n"\
           "freq: {}\n"\
           "temp: {}\n".format( time, freq, temp )

答案 8 :(得分:1)

我来到这里寻找一个简单的1-liner来删除/更正用于打印的文档字符串的识别级别 ,而不会让它看起来不整洁,例如通过制作它在剧本中“悬挂在功能之外”。

这是我最终做的事情:

import string
def myfunction():

    """
    line 1 of docstring
    line 2 of docstring
    line 3 of docstring"""

print str(string.replace(myfunction.__doc__,'\n\t','\n'))[1:] 

显然,如果你用空格缩进(例如4)而不是tab键,那就改用这样的东西:

print str(string.replace(myfunction.__doc__,'\n    ','\n'))[1:]

如果您希望文档字符串看起来像这样,则不需要删除第一个字符:

    """line 1 of docstring
    line 2 of docstring
    line 3 of docstring"""

print string.replace(myfunction.__doc__,'\n\t','\n') 

答案 9 :(得分:1)

第一个选项是好选项 - 包括缩进。 它是python风格 - 提供代码的可读性。

要正确显示:

print string.lstrip()

答案 10 :(得分:0)

这取决于您希望文本显示的方式。如果你想让它全部左对齐,那么要么像在第一个片段中那样对它进行格式化,要么迭代左边的行 - 修剪所有空格。

答案 11 :(得分:0)

对于字符串,您可以在处理字符串之后。对于文档字符串,您需要在处理函数之后。这是两个仍然可读的解决方案。

class Lstrip(object):
    def __rsub__(self, other):
        import re
        return re.sub('^\n', '', re.sub('\n$', '', re.sub('\n\s+', '\n', other)))

msg = '''
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
      tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
      veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
      commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
      velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
      cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id
      est laborum.
      ''' - Lstrip()

print msg

def lstrip_docstring(func):
    func.__doc__ = func.__doc__ - Lstrip()
    return func

@lstrip_docstring
def foo():
    '''
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
    veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
    commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
    velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
    cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id
    est laborum.
    '''
    pass


print foo.__doc__

答案 12 :(得分:0)

我遇到了类似的问题,使用多行代码后,代码真的变得不可读,我想到了类似的东西

print("""aaaa
"""   """bbb
""")

是的,一开始看起来很糟糕,但是嵌入式语法非常复杂,最后添加一些内容(例如'\ n“')并不是解决方案

答案 13 :(得分:0)

您可以使用此功能 trim_indent

import re


def trim_indent(s: str):
    s = re.sub(r'^\n+', '', s)
    s = re.sub(r'\n+$', '', s)
    spaces = re.findall(r'^ +', s, flags=re.MULTILINE)
    if len(spaces) > 0 and len(re.findall(r'^[^\s]', s, flags=re.MULTILINE)) == 0:
        s = re.sub(r'^%s' % (min(spaces)), '', s, flags=re.MULTILINE)
    return s


print(trim_indent("""


        line one
            line two
                line three
            line two
        line one


"""))

结果:

"""
line one
    line two
        line three
    line two
line one
"""

答案 14 :(得分:-2)

我有时会将多行文字作为字符串列表编写,然后将它们连接起来......

    part = "".join([
        "\x00\x00\x00\x00\x0C\x00\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00"
        "\x00\x00\x00\x00\x0C\x00\x00\x00\x00\xFF\x00\x00\x00\x00\x00\x00",
        "\x00\x00\x00\x00\x0C\x00\x00\x00\x00\x00\xFF\x00\x00\x00\x00\x00",
        "\x00\x00\x00\x00\x0C\x00\x00\x00\x00\x00\x00\xFF\x00\x00\x00\x00",
    ])

它不是最有效的方式,但对于大多数用例来说它的性能足够高并且它不会弄乱你的缩进或要求第一行与第二行有不同的缩进,就像引用的三元组一样方法