Cadena de varias líneas con argumentos. ¿Cómo declarar?

Digamos que tengo una cadena extremadamente larga con argumentos que quiero crear. Sé que puedes crear una cadena multilínea con

cmd = """line 1
      line 2
      line 3"""

Pero ahora digamos que quiero pasar 1, 2 y 3 como argumentos.

Esto funciona

cmd = """line %d
      line %d
      line %d""" % (1, 2, 3)

Pero si tengo una cadena súper larga con más de 30 argumentos, ¿cómo puedo pasar esos argumentos en varias líneas? Pasarlos en una sola línea anula el propósito de incluso intentar crear una cadena de varias líneas.

Gracias a cualquiera de antemano por su ayuda y conocimiento.

preguntado el 11 de junio de 12 a las 19:06

10 Respuestas

Podrías usar el str.format() función, que permite argumentos con nombre, por lo que:

'''line {0}
line {1}
line {2}'''.format(1,2,3)

Por supuesto, podría extender esto usando Python's *args sintaxis para permitirle pasar un tuple or list:

args = (1,2,3)
'''line {0}
line {1}
line {2}'''.format(*args)

Si puede nombrar inteligentemente sus argumentos, la solución más robusta (aunque la más intensiva en escritura) sería usar Python's **kwargs sintaxis para pasar en un diccionario:

args = {'arg1':1, 'arg2':2, 'arg3':3}
'''line {arg1}
line {arg2}
line {arg3}'''.format(**args)

Para obtener más información sobre el str.format() minilenguaje, vaya aquí.

Respondido el 15 de junio de 18 a las 08:06

+1 El formato ** kwargs es excelente para la legibilidad en muchos escenarios (aunque quizás no sea el ejemplo del OP). - casey kuball

La '''string here''' La técnica es una técnica sólida y funciona bien, pero crea un código fuente REALMENTE FEO cuando tiene que alinear a la izquierda todo menos la primera línea y su código fuente tiene una sangría de varios niveles. Para obtener un código fuente bonito y fácil de ver con una buena alineación, por lo tanto, use mi técnica aquí en su lugar: stackoverflow.com/a/54564926/4561887. Tiene sus inconvenientes, por supuesto, pero para algo menos que un párrafo largo de texto, me gusta esta otra técnica sobre el uso de la ''' ''' técnica. - grapas gabriel

Consulte esta impresión de cadena de documentos autodocumentada, como documentación del módulo, que utiliza el tipo de técnica que presenta anteriormente. Lo acabo de agregar al final de mi respuesta aquí: stackoverflow.com/a/54564926/4561887. - grapas gabriel

Si tiene llaves en su cadena, escápelas usando llaves dobles: {{ y }} - LoMaPh

Podría abusar de las propiedades de continuación de línea del paréntesis ( y la coma ,.

cmd = """line %d
      line %d
      line %d""" % (
      1,
      2,
      3)

Respondido el 11 de junio de 12 a las 19:06

Muchas gracias. Exactamente lo que estaba buscando. Nunca supe que podría tener varias líneas al usar corchetes. Esto es de gran ayuda!!! - Trillón

La forma más fácil podría ser usar interpolación de cadena literal (disponible desde Python 3.6 en adelante y suponiendo que todos los argumentos estén dentro del alcance).

cmd = f"""line {1}
      line {2}
      line {3}"""

Respondido 23 ago 17, 11:08

gracias, pero esto no funciona bien en la situación en que la cadena original contiene muchos corchetes: luk aron

¿Por qué esta no es la mejor manera? Es mucho más legible y mucho más fácil de escribir. - Akshay

Una variante más con la función string.format().

s = "{0} " \
    "{1} " \
    "{2}" \
    .format("Hello", "world", "from a multiline string")    
print(s)

Respondido 23 ago 17, 11:08

TLDR;

Salta hacia abajo y mira los Ejemplos 1 y 4 a continuación.

Respuesta completa:

Apenas aprendí sobre el Python textwrap módulo la semana pasada (octubre de 2020), con su muy útil textwrap.dedent() función, y teniendo en cuenta ha existido desde Python 2.7¡No puedo creer que no sea más popular!

Usar textwrap.dedent() alrededor de una cadena de varias líneas resuelve todos los problemas de mi respuesta anterior!

Aquí está la documentación oficial al respecto. (énfasis añadido):

textwrap.dedent(text)

Elimine cualquier espacio en blanco inicial común de cada línea de texto.

Esto se puede usar para hacer que las cadenas entre comillas triples se alineen con el borde izquierdo de la pantalla, sin dejar de presentarlas en el código fuente con sangría.

Tenga en cuenta que las tabulaciones y los espacios se tratan como espacios en blanco, pero no son iguales: las líneas " hello" y "\thello" se considera que no tienen espacios en blanco iniciales comunes.

Las líneas que contienen solo espacios en blanco se ignoran en la entrada y se normalizan a un solo carácter de nueva línea en la salida.

Por ejemplo:

def test():
    # end first line with \ to avoid the empty line!
    s = '''\
    hello
      world
    '''
    print(repr(s))          # prints '    hello\n      world\n    '
    print(repr(dedent(s)))  # prints 'hello\n  world\n'

Para todos los ejemplos

import textwrap

ejemplo 1

¿Entonces en lugar de esto, ya que los estados de respuesta más votados (esto pierde la sangría agradable y limpia):

cmd = '''line {0}
line {1}
line {2}'''.format(1,2,3)

print(cmd)

Haga esto (¡Y MANTENGA la sangría agradable y limpia)!

import textwrap

cmd = textwrap.dedent('''\
    line {0}
    line {1}
    line {2}''').format(1,2,3)

print(cmd)

O, usando el nuevo y mejorado de Python3 cadenas de formato "f" en vez de .format() ¡método!:

import textwrap

var0 = 1
var1 = 2
var2 = 3
cmd = textwrap.dedent(f'''\
    line {var0}
    line {var1}
    line {var2}''')

print(cmd)

ejemplo 2

Si tienes muchos argumentos para la format() función, puede ponerlos en varias líneas si lo desea. Note que el format() argumentos ocupan dos líneas aquí:

cmd = textwrap.dedent('''\
    line {0}
    line {1}
    line {2}
    line {3}
    line {4}
    line {5}
    line {6}
    line {7}
    line {8}
    line {9}
    line {10}
    line {11}
    line {12}
    line {13}
    line {14}
    line {15}
    line {16}
    line {17}
    line {18}
    line {19}''').format(
        1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
        11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    )

print(cmd)

Y por supuesto, si el format() los argumentos son realmente largos, también puede poner cada argumento en su propia línea:

cmd = textwrap.dedent('''\
    line {0}
    line {1}
    line {2}
    line {3}
    line {4}
    line {5}
    line {6}
    line {7}
    line {8}
    line {9}
    line {10}
    line {11}
    line {12}
    line {13}
    line {14}
    line {15}
    line {16}
    line {17}
    line {18}
    line {19}''').format(
        100000000000000000000000000000000000000000000000000000000000000000001,
        100000000000000000000000000000000000000000000000000000000000000000002,
        100000000000000000000000000000000000000000000000000000000000000000003,
        100000000000000000000000000000000000000000000000000000000000000000004,
        100000000000000000000000000000000000000000000000000000000000000000005,
        100000000000000000000000000000000000000000000000000000000000000000006,
        100000000000000000000000000000000000000000000000000000000000000000007,
        100000000000000000000000000000000000000000000000000000000000000000008,
        100000000000000000000000000000000000000000000000000000000000000000009,
        100000000000000000000000000000000000000000000000000000000000000000010,
        100000000000000000000000000000000000000000000000000000000000000000011,
        100000000000000000000000000000000000000000000000000000000000000000012,
        100000000000000000000000000000000000000000000000000000000000000000013,
        100000000000000000000000000000000000000000000000000000000000000000014,
        100000000000000000000000000000000000000000000000000000000000000000015,
        100000000000000000000000000000000000000000000000000000000000000000016,
        100000000000000000000000000000000000000000000000000000000000000000017,
        100000000000000000000000000000000000000000000000000000000000000000018,
        100000000000000000000000000000000000000000000000000000000000000000019,
        100000000000000000000000000000000000000000000000000000000000000000020,
    )

print(cmd)

ejemplo 3

Y también debes en lugar de esto, como dije en mi respuesta original (que mantiene una sangría bonita pero es un poco tedioso de usar):

print("\n\n" + 
      "########################\n" + 
      "PRINT DOCSTRING DEMO:\n" + 
      "########################")

...tu puedes ahora ¡hacer esto!--lo que permite que mis cadenas de varias líneas, cuando se imprimen, "se alineen con el borde izquierdo de la pantalla, sin dejar de presentarlas en el código fuente con sangría" (ver documentación oficial):

# Note: use the `\` below to prevent the implicit newline right after it from being printed.
print(textwrap.dedent("""

      ########################
      PRINT DOCSTRING DEMO:
      ########################\
      """))

ejemplo 4

Y también debes en lugar de esto, que tiene una fea falta de sangría justo en el medio:

def printDocstrings1():
    """
    Print all document strings for this module, then exit.
    Params:  NA
    Returns: NA
    """

    # A LITTLE BIT UGLY, BUT IT WORKS.
    print("""
---------------------
Module Documentation:
---------------------
printDocstrings:{}
myFunc1:{}
class Math:{}
    __init__:{}
    add:{}
    subtract:{}""".format(
        printDocstrings1.__doc__,
        myFunc1.__doc__,
        Math.__doc__,
        Math.__init__.__doc__,
        Math.add.__doc__,
        Math.subtract.__doc__))

...hacer esto, Que utiliza textwrap.dedent() ¡para mantener una sangría agradable en todo momento!:

def printDocstrings2():
    """
    Print all document strings for this module, then exit.
    Params:  NA
    Returns: NA
    """

    # MUCH CLEANER! Now I can have the proper indentation on the left withOUT
    # it printing that indentation!
    print(textwrap.dedent("""\
    ---------------------
    Module Documentation:
    ---------------------
    printDocstrings:{}
    myFunc1:{}
    class Math:{}
        __init__:{}
        add:{}
        subtract:{}""").format(
            printDocstrings2.__doc__,
            myFunc1.__doc__,
            Math.__doc__,
            Math.__init__.__doc__,
            Math.add.__doc__,
            Math.subtract.__doc__))

Ejecuta el código de arriba

Puede ejecutar mi código de prueba anterior en mi eRCaGuy_hola_mundo repositorio de GitHub aquí: textwrap_practice_1.py.

Ejecutar comando:

./textwrap_practice_1.py

O:

python3 textwrap_practice_1.py

Respondido 18 Abr '21, 20:04

Actualización 19 de octubre de 2020: aunque mi respuesta aquí sigue siendo perspicaz, informativa y vale la pena leerla, tengo a mejor respuesta aquí ahora que se basa en lo realmente útil textwrap.dedent() función.


As @Chinmay Kanchi dice, tu puedes hacer:

'''line {0}
line {1}
line {2}'''.format(1,2,3)

Sin embargo, creo que se ve tonto con la alineación que tiene que estar completamente alineada a la izquierda en las nuevas líneas, especialmente cuando ya está haciendo esto con varios niveles de sangría, por lo que preferiría que se escribiera más así:

'''line {0}
   line {1}
   line {2}'''.format(1,2,3)

¡Eso funciona, PERO ESTÁ MAL! Interpreta todos los espacios a la izquierda de line {1} y line {2} como espacios reales, por lo que imprimirlo se verá ridículo:

1
   2
   3

En lugar de

1
2
3

Entonces, una solución alternativa es usar el + operador para concatenar y paréntesis alrededor de la cadena concatenada, así como una nueva línea explícita (\n) caracteres, como este:

('line {0}\n' + 
 'line {1}\n' +
 'line {2}').format(1,2,3)

Perfecto (en mi opinión)! Ahora se ve bien y alineado tanto en el código fuente como en la cadena real si lo imprime.

Ejemplo completo:

¡Código fuente FEO!

num1 = 7
num2 = 100
num3 = 75.49

# Get some levels of indentation to really show the effect well.
# THIS IS *UGLY*! Notice the weird forced-left-align thing for the string I want to print!
if (True):
    if (True):
        if (True):
            # AAAAAH! This is hard to look at!
            print('''num1 = {}
num2 = {}
num3 = {}'''.format(num1, num2, num3))

            # More lines of code go here
            # etc
            # etc

Salida:

número1 = 7
número2 = 100
número3 = 75.49

Bonito ejemplo! Ahh, tan agradable de ver en el código fuente. :)

Esto es lo que prefiero.

# Get some levels of indentation to really show the effect well.
if (True):
    if (True):
        if (True):
            # IMPORTANT: the extra set of parenthesis to tie all of the concatenated strings together here is *required*!
            print(('num1 = {}\n' + 
                   'num2 = {}\n' + 
                   'num3 = {}')
                   .format(num1, num2, num3))

            # More lines of code go here
            # etc
            # etc

Salida:

número1 = 7
número2 = 100
número3 = 75.49

Actualización 21 de mayo de 2019: ¡A veces, la cadena de varias líneas "fea" es realmente la mejor manera de hacerlo!

Entonces, he estado usando Python para generación automática de encabezado C y archivos fuente (.h/.c) a partir de archivos de configuración basados ​​en texto, y después de hacer una buena cantidad de esto, llegué a la conclusión de que los beneficios de simplemente copiar y pegar grandes fragmentos de texto de un archivo de configuración en mi script de Python superan cualquier factor de "fealdad".

Por lo tanto, he determinado que la siguiente es mi forma preferida de hacerlo cuando se requiere una cadena copiada y pegada de varias líneas, por ejemplo:

Opción 1

  • Use paréntesis alrededor de toda la cadena larga para permitir la apertura """ estar en una nueva línea

    Obtenga algunos niveles de sangría para mostrar aún el efecto de "fealdad".

    if (True): if (True): if (True): header = ( """ /* mi información de encabezado de archivo personalizado aquí */

    #pragma una vez

    #incluir "{}"

    constante {} {}; """).formato(incluir, struct_t, estructura)

              print("header =" + header)
    

Opción 2

  • Sin paréntesis, pero aún poner el cierre """ en su propia linea

    Obtenga algunos niveles de sangría para mostrar aún el efecto de "fealdad".

    if (True): if (True): if (True): header = """ /* mi información de encabezado de archivo personalizado aquí */

    #pragma una vez

    #incluir "{}"

    constante {} {}; """.formato(incluir, struct_t, estructura)

              print("header =" + header)
    

Opción 3

  • Sin paréntesis alrededor de toda la cadena, y poner el cierre """ en la misma línea que el contenido de la cadena para evitar agregar un (potencialmente indeseable) \n al final.

  • Sin embargo, ponga el resto de format( en una nueva línea (o en muchas líneas nuevas) en caso de que sea larga.

    Obtenga algunos niveles de sangría para mostrar aún el efecto de "fealdad".

    if (True): if (True): if (True): header = """ /* mi información de encabezado de archivo personalizado aquí */

    #pragma una vez

    #incluir "{}"

    const {} {};""".format( include, struct_t, struct) # sangría aquí puede ser literalmente cualquier cosa, pero me gusta sangrar 1 nivel; ya que está entre paréntesis, sin embargo, no importa

              print("header =" + header)
    

Salida:

  • Las opciones 1 y 2 producen una salida exactamente idéntica, con un extra \n al final de la cadena, lo cual está bien en la mayoría de los casos
  • La opción 3 produce exactamente el mismo resultado que las opciones 1 y 2 excepto que lo hace no tener el extra \n al final de la cadena, en caso de que no sea deseable para su caso
  • Ya sea que use la opción 1, 2 o 3 realmente no importa, es solo la preferencia del usuario en este punto, aparte del extra \n como se señaló justo arriba

Esto es lo que se imprime en las opciones 1, 2 y 3 anteriores:

/*
my custom file header info here
*/

#pragma once

#include "<stdint.h>"

const my_struct_t my_struct;


PONIENDO TODO JUNTO: una combinación de los métodos "bonito" y "feo" para obtener el mejor resultado en esta demostración de impresión cadena de documentación documentación para su módulo!

Aquí hay un ejemplo básico del uso de los métodos de cadena de varias líneas "bonito" y "feo" presentados anteriormente para obtener los mejores beneficios de cada uno. Esto también muestra cómo usar e imprimir módulos "docstrings" para documentar su módulo. Fíjate cómo el """-basada en la técnica de líneas múltiples nos brinda un gran espacio porque, de la forma en que lo hice a continuación, hay una nueva línea automática (\n) después de la apertura """ y antes del cierre """ ya que así es como se escribe la cadena.

# PRETTY, AND GOOD.
print("\n\n" + 
      "########################\n" + 
      "PRINT DOCSTRING DEMO:\n" + 
      "########################")

import sys

def printDocstrings():
    """
    Print all document strings for this module, then exit.
    Params:  NA
    Returns: NA
    """

    # A LITTLE BIT UGLY, BUT GOOD! THIS WORKS GREAT HERE!
    print("""
---------------------
Module Documentation:
---------------------
printDocstrings:{}
myFunc1:{}
class Math:{}
    __init__:{}
    add:{}
    subtract:{}""".format(
        printDocstrings.__doc__,
        myFunc1.__doc__,
        Math.__doc__,
        Math.__init__.__doc__,
        Math.add.__doc__,
        Math.subtract.__doc__))

    sys.exit()

def myFunc1():
    """
    Do something.
    Params:  NA
    Returns: NA
    """
    pass

class Math:
    """
    A basic "math" class to add and subtract
    """

    def __init__(self):
        """
        New object initialization function.
        Params:  NA
        Returns: NA
        """
        pass

    def add(a, b):
        """
        Add a and b together.
        Params:  a   1st number to add
                 b   2nd number to add
        Returns: the sum of a + b
        """
        return a + b

    def subtract(a, b):
        """
        Subtract b from a.
        Params:  a   number to subtract from
                 b   number to subtract
        Returns: the result of a - b
        """
        return a - b

printDocstrings() 

Salida:
- ¡Observe cuán bonito y bien formateado es todo automáticamente, ya que las pestañas, las nuevas líneas y el espaciado de sus cadenas de documentos se conservan automáticamente cuando los imprime de esta manera!

  
########################  
PRINT DOCSTRING DEMO:  
########################  
  
---------------------  
Module Documentation:  
---------------------  
printDocstrings:  
    Print all document strings for this module, then exit.  
    Params:  NA  
    Returns: NA  
      
myFunc1:  
    Do something.  
    Params:  NA  
    Returns: NA  
      
class Math:  
    A basic "math" class to add and subtract  
      
    __init__:  
        New object initialization function.  
        Params:  NA  
        Returns: NA  
          
    add:  
        Add a and b together.  
        Params:  a   1st number to add  
                 b   2nd number to add  
        Returns: the sum of a + b  
          
    subtract:  
        Subtract b from a.  
        Params:  a   number to subtract from  
                 b   number to subtract  
        Returns: the result of a - b  
          
  

Referencias:

  1. Cadenas de documentación de Python: https://www.geeksforgeeks.org/python-docstrings/
  • Nota: también puede utilizar el help() método para acceder a la documentación de un módulo o clase (pero de manera interactiva), como se muestra en el enlace de arriba, así:

         help(Math)  # to interactively display Class docstring
         help(Math.add)  # to interactively display method's docstring 
    

Respondido el 13 de diciembre de 21 a las 16:12

Para tener los argumentos en la misma línea en que se insertan, podría hacerlo así:

cmd = "line %d\n"%1 +\
      "line %d\n"%2 +\
      "line %d\n"%3

[EDIT:] En respuesta al primer comentario se me ocurrió esto:

cmd = "\n".join([
      "line %d"%1,
      "line %d"%2,
      "line %d"%3])

Respondido el 11 de junio de 12 a las 19:06

Hacer eso con más de 30 argumentos no sería muy eficiente. "".join() en una lista, por otro lado... :) - Frederic Hamidi

Puedes utilizar textwrap.dedent para eliminar los espacios iniciales de las líneas:

import textwrap

cmd = str.strip(textwrap.dedent(
    '''
        line {}
            line with indent
        line {}
        line {}
    '''
    .format(1, 2, 3)))

Esto resulta en:

line 1
    line with indent
line 2
line 3

respondido 15 mar '19, 15:03

Voten, aquellos que usan PyCharm: youtrack.jetbrains.com/issue/PY-34646. Lo que hace el formato automático y las reglas de verificación de formato no son consistentes en el fragmento de la pregunta. - Jorge Sovetov

Esto funciona para mi:

cmd = """line %d
      line %d
      line %d""" % (
          1,
          2,
          3
      )

Respondido el 11 de junio de 12 a las 19:06

Aquí está la versión más simple, que también es compatible con IDE en términos de verificación format argumentos:

cmd = (
    'line {}\n'
    'line {}\n'
    'line {}\n'
    .format(1, 2, 3))

Versión de argumentos multilínea:

cmd = (
    'line {}\n'
    'line {}\n'
    'line {}\n'
    .format(
        'very very very very very very very very very long 1',
        'very very very very very very very very very long 2',
        'very very very very very very very very very long 3',
    )
)

respondido 15 mar '19, 15:03

Voten, aquellos que usan PyCharm: youtrack.jetbrains.com/issue/PY-34646. El formato automático y la verificación de formato no son consistentes en el fragmento de la pregunta. - Jorge Sovetov

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.