Python是否具有用于取消多行字符串的内置函数?

Hub*_*bro 41 python string indentation

说我有字符串

s = """
    Controller = require 'controller'

    class foo
        view: 'baz'
        class: 'bar'

        constructor: ->
            Controller.mix @
"""
Run Code Online (Sandbox Code Playgroud)

字符串中的每一行现在都有一个全局4空格缩进.如果在函数内声明了这个字符串,它将有一个8空格的全局缩进等.

Python是否具有删除字符串的全局左缩进的功能?

我希望该函数输出为:

Controller = require 'controller'

class foo
    view: 'baz'
    class: 'bar'

    constructor: ->
        Controller.mix @"
Run Code Online (Sandbox Code Playgroud)

Sve*_*ach 78

不是内置函数,而是标准库中的函数: textwrap.dedent()

>>> print(textwrap.dedent(s))

Controller = require 'controller'

class foo
    view: 'baz'
    class: 'bar'

    constructor: ->
        Controller.mix @
Run Code Online (Sandbox Code Playgroud)

  • @Anthon:如果你将第一个换行符转换为`s ="""\`,那么`dedent`将不会产生第一个空行. (5认同)
  • 我不知道有一个存在。有用的东西。+1。 (3认同)
  • @firegurafiku 当然不是,它不会产生它,因为它不存在。真正的问题是它在 ** 在那里** 时不会把它拿走,而这正是 OP 所要求的。 (2认同)

小智 14

我知道这个问题已经得到了回答,但也有这种方式:

import inspect

def test():
    t = """
    some text
    """

    return inspect.cleandoc(t)

print(test())
Run Code Online (Sandbox Code Playgroud)

  • 在某些情况下,这比“textwrap.dedent”更好,因为它还会删除尾随和前导的换行符。 (4认同)

Ant*_*hon 8

textwrap.dedent()接近你想要的,但它没有实现你所要求的,因为它有一个领先的换行符.你可以dedent用一个函数来包装前导换行s:

def my_dedent(string):
    if string and string[0] == '\n':
        string = string[1:]
    return textwrap.dedent(string)
Run Code Online (Sandbox Code Playgroud)

但是textwrap.dedent(),如果从缩进多行语句生成Python源,其中尾随空格无关紧要,则以特殊方式处理只有空格的行.

但一般来说,textwrap.dedent()从具有比"最大缩进"更多的空格的行中删除额外的空格是不合适的,从所有空格行中删除空格并在结束之前描述任何空格""",特别是因为此行为未记录并且使用非透明完成正则表达式.

由于我还生成非Python源代码,其中空格通常很重要,我使用以下例程.它不处理TAB缩进,但它确实为您提供了在没有前导换行符的情况下提出的输出,其中textwrap.dedent()失败了.

def remove_leading_spaces(s, strict=False):
    '''Remove the maximum common spaces from all non-empty lines in string

Typically used to remove leading spaces from all non-empty lines in a
multiline string, preserving all extra spaces.
A leading newline (when not useing '"""\') is removed unless the strict
argument is True.

Note that if you want two spaces on the last line of the return value 
without a newline, you have to use the max indentation + 2 spaces before 
the closing """. If you just input 2 spaces that is likely to be the 
maximum indent.
    '''
    if s and not strict and s[0] == '\n':
        s = s[1:]
    lines = s.splitlines(True) # keep ends
    max_spaces = -1
    for line in lines:
        if line != '\n':
            for idx, c in enumerate(line[:max_spaces]):
                if not c == ' ':
                    break
            max_spaces = idx + 1
    return ''.join([l if l == '\n' else l[max_spaces-1:] for l in lines])
Run Code Online (Sandbox Code Playgroud)