414 votos

Muesca apropiada para las cadenas multilíneas Python

¿Qué es la muesca apropiada para las cadenas multilíneas Python dentro de una función?

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

o

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

¿u otra cosa?

Parece extraño que la cadena colgando fuera de la función en el primer ejemplo.

Gracias.

427voto

Mike Graham Puntos 22480

Usted probablemente querrá línea con el """

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

Desde los saltos de línea y los espacios están incluidos en la propia cadena, tendrás que postproceso. Si usted no quiere hacer eso, y usted tiene un montón de texto, puede almacenar por separado en un archivo de texto. Si un archivo de texto no funciona bien para su aplicación y no quieres postproceso, probablemente me vaya con el

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

Si desea postproceso una de varias líneas de cadena, recorte las partes que no necesita, usted debe considerar la textwrap de módulo o de la técnica para el procesamiento posterior docstrings presentado en 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)

233voto

bignose Puntos 6573

La textwrap.dedent función permite iniciar con la correcta indentación en la fuente, y luego se tira desde el texto antes de su uso.

El trade-off, como indicaron algunos otros, es que esto es un extra de la función de llamada en el literal; tener esto en cuenta a la hora de decidir dónde colocar estos literales en su código.

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)

El trailing \ en el mensaje de registro literal es asegurar que el salto de línea no está en el literal; de esta manera, el literal, pero no comenzar con una línea en blanco, y en su lugar se inicia con la siguiente línea completa.

El valor de retorno textwrap.dedent es la cadena de entrada con todos los principales espacios de sangría eliminado en cada línea de la cadena, lo que significa que la anterior log_message valor estará alineado a la izquierda, excepto por la mayor sangría de tercera línea.

17voto

Joop Puntos 1108

Algunas opciones más. En Ipython con pylab habilitado, dedent ya está en el espacio de nombres. He comprobado y es a partir de matplotlib. O puede ser importado con:

from matplotlib.cbook import dedent

En la documentación que afirma que es más rápido que el textwrap equivalente a uno y en mis pruebas en ipython de hecho, es 3 veces más rápido en promedio con mis pruebas rápidas. También tiene la ventaja de que se descarta cualquier principales líneas en blanco, esto le permite ser flexible en la forma de construir la cadena:

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

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

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

El uso de la matplotlib dedent en estos tres ejemplos nos dan la misma sensato resultado. El textwrap dedent función tendrá un líder en línea en blanco con el 1er ejemplo.

Desventaja obvia es que textwrap está en la biblioteca estándar, mientras que matplotlib es módulo externo.

Algunos de los equilibrios aquí... la dedent funciones hacen que el código sea más legible, donde las cadenas obtener definidos, pero requieren de un procesamiento posterior para obtener el string en formato utilizable. En docstrings es obvio que usted debe utilizar correctamente la sangría como la mayoría de los usos de la docstring va a hacer los tratamientos necesarios.

Cuando me necesita una cadena larga en mi código me parece la siguiente es cierto que feo el código en el que me deje la larga cadena de dejar fuera de la envolvente de la sangría. Definitivamente falla en "Hermoso es mejor que feo.", pero uno podría argumentar que es más simple y más explícita que la dedent alternativa.

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()

1voto

James Gowdy Puntos 19

He venido aquí en busca de una simple 1-funda para eliminar o corregir la identation nivel de la docstring para la impresión, sin hacer que se vea desordenado, por ejemplo, haciendo que se "cuelgue fuera de la función" dentro de la secuencia de comandos.

He aquí lo que hice:

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:] 

Obviamente, si estás sangría con espacios (ej. 4) en lugar de la tecla tab usar algo como esto en su lugar:

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

Y no es necesario quitar el primer carácter, si te gusta tu docstrings parecerse a este lugar:

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

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

0voto

Depende de cómo desea que el texto que se muestra. Si lo quieres todo para ser alineado a la izquierda a continuación formatearlo como en el primer fragmento o iterar a través de la líneas de izquierda poda todo el espacio.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X