¿Python tiene una función incorporada para quitar la sangría de una cadena multilínea?

Resuelto Hubro asked hace 12 años • 4 respuestas

Di que tengo la cuerda

s = """
    Controller = require 'controller'

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

        constructor: ->
            Controller.mix @
"""

Cada línea de la cadena ahora tiene una sangría global de 4 espacios. Si esta cadena se declarara dentro de una función, tendría una sangría global de 8 espacios, etc.

¿Tiene Python una función para eliminar la sangría izquierda global de una cadena?

Me gustaría que la salida de esa función fuera:

Controller = require 'controller'

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

    constructor: ->
        Controller.mix @"
Hubro avatar Jun 22 '12 20:06 Hubro
Aceptado

No es una función incorporada, sino una función en la biblioteca estándar: textwrap.dedent()

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

Controller = require 'controller'

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

    constructor: ->
        Controller.mix @
Sven Marnach avatar Jun 22 '2012 13:06 Sven Marnach

Sé que esta pregunta ya ha sido respondida pero también existe esta manera:

import inspect

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

    return inspect.cleandoc(t)

print(test())
iSplasher avatar Mar 06 '2019 13:03 iSplasher

textwrap.dedent()está cerca de lo que desea, pero no implementa lo que solicitó porque tiene una nueva línea inicial. Puede incluir dedentuna función que elimine la nueva línea inicial de s:

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

Sin embargo, textwrap.dedent()maneja líneas con solo espacios en blanco de una manera especial, lo cual está bien si está generando una fuente de Python a partir de una declaración de sangría de varias líneas, donde los espacios en blanco al final son insignificantes.

Pero, en general, es inapropiado textwrap.dedent()eliminar espacios en blanco adicionales de líneas con más espacios en blanco que la 'sangría máxima', eliminar espacios en blanco de todas las líneas de espacios en blanco y descartar cualquier espacio en blanco antes del cierre """, especialmente porque este comportamiento no está documentado y se realiza con elementos no transparentes. expresiones regulares .

Como también genero código fuente que no es Python, donde los espacios suelen ser significativos, utilizo la siguiente rutina. No maneja la sangría TAB, pero le brinda el resultado que solicitó sin una nueva línea inicial, donde textwrap.dedent()falla.

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])
Anthon avatar Mar 17 '2013 12:03 Anthon