Mehrzeilige Zeichenfolge mit Argumenten. Wie deklarieren?

72

Angenommen, ich habe eine extrem lange Zeichenfolge mit Argumenten, die ich erstellen möchte. Ich weiß, dass Sie mit eine mehrzeilige Zeichenfolge erstellen können

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

Angenommen, ich möchte 1, 2 und 3 als Argumente übergeben.

Das funktioniert

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

Aber wenn ich eine super lange Zeichenfolge mit mehr als 30 Argumenten habe, wie kann ich diese Argumente möglicherweise in mehreren Zeilen übergeben? Wenn Sie sie in einer einzelnen Zeile übergeben, wird nicht einmal versucht, eine mehrzeilige Zeichenfolge zu erstellen.

Vielen Dank an alle im Voraus für ihre Hilfe und ihren Einblick.

Billionen
quelle

Antworten:

43

Sie könnten die Zeilenfortsetzungseigenschaften der Klammer (und des Kommas missbrauchen ,.

cmd = """line %d
      line %d
      line %d""" % (
      1,
      2,
      3)
Frédéric Hamidi
quelle
1
Vielen Dank. Genau das, wonach ich gesucht habe. Ich hätte nie gedacht, dass ich bei der Verwendung von Klammern mehrere Zeilen haben könnte. Das ist eine große Hilfe !!!
Quillion
89

Sie können die str.format()Funktion verwenden, die benannte Argumente zulässt, also:

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

Sie können dies natürlich mithilfe der Python- *argsSyntax erweitern, damit Sie ein tupleoder übergeben können list:

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

Wenn Sie Ihre Argumente intelligent benennen können, besteht die robusteste Lösung (obwohl die typintensivste) darin, die Python- **kwargsSyntax zu verwenden, um ein Wörterbuch zu übergeben:

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

Weitere Informationen zur str.format()Minisprache finden Sie hier .

Chinmay Kanchi
quelle
1
+1 Das ** kwargs-Format ist für viele Szenarien gut lesbar (obwohl es möglicherweise nicht das Beispiel des OP ist).
Casey Kuball
Die '''string here'''Technik ist eine solide Technik und funktioniert gut, aber sie erzeugt einen WIRKLICH HÄSSLICHEN Quellcode, wenn Sie alle bis auf die erste Zeile linksbündig ausrichten müssen und Ihr Quellcode mehrere Ebenen eingerückt ist. Verwenden Sie hier stattdessen meine Technik, um einen hübschen und übersichtlichen Quellcode mit guter Ausrichtung zu erhalten: stackoverflow.com/a/54564926/4561887 . Es hat natürlich seine Nachteile, aber für weniger als einen langen Textabschnitt mag ich diese andere Technik gegenüber der Verwendung der ''' '''Technik.
Gabriel Staples
Schauen Sie sich diesen selbstdokumentierenden Docstring-Druck als Moduldokumentation an, bei dem die oben beschriebene Technik verwendet wird. Ich habe es gerade am Ende meiner Antwort hier hinzugefügt : stackoverflow.com/a/54564926/4561887 .
Gabriel Staples
Wenn Sie geschweifte Klammern in Ihrer Zeichenfolge haben, können Sie diese mit doppelten geschweiften Klammern
umgehen
24

Der einfachste Weg ist möglicherweise die Verwendung der Literal-String-Interpolation (verfügbar ab Python 3.6 und unter der Annahme, dass alle Argumente im Geltungsbereich liegen).

cmd = f"""line {1}
      line {2}
      line {3}"""
Michael Mauderer
quelle
danke, aber das funktioniert nicht gut in der Situation, dass die ursprüngliche Zeichenfolge viele Klammern enthält
Luk Aron
16

Eine weitere Variante mit der Funktion string.format () -.

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

Update 19. Oktober 2020: Obwohl meine Antwort hier immer noch aufschlussreich, informativ und lesenswert ist, habe ich hier jetzt eine viel bessere Antwort, die auf der wirklich nützlichen textwrap.dedent()Funktion beruht .


Wie @Chinmay Kanchi sagt , können Sie Folgendes tun:

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

Ich denke jedoch, dass es doof aussieht, wenn die Ausrichtung auf neuen Zeilen vollständig linksbündig sein muss, insbesondere wenn Sie dies bereits mit mehreren eingerückten Ebenen tun. Daher würde ich es vorziehen, wenn es eher so geschrieben wird:

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

Das funktioniert, ABER IST FALSCH! Es interpretiert alle Leerzeichen links von line {1}und line {2}als reale Leerzeichen, sodass das Drucken doof aussieht:

1
   2
   3

Anstatt von

1
2
3

Eine Problemumgehung besteht also darin, den +Operator zum Verketten und die Klammer um die verkettete Zeichenfolge sowie explizite \nZeichen für new-line ( ) wie folgt zu verwenden :

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

Perfekt (meiner Meinung nach)! Jetzt sieht es gut aus und ist sowohl im Quellcode als auch in der eigentlichen Zeichenfolge ausgerichtet, wenn Sie es drucken.

Vollständiges Beispiel:

Hässlicher Quellcode!

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

Ausgabe:

num1 = 7
num2 = 100
num3 = 75,49

Hübsches Beispiel! Ahh, so schön im Quellcode anzusehen. :) :)

Das ist was ich bevorzuge.

# 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

Ausgabe:

num1 = 7
num2 = 100
num3 = 75,49

Update 21. Mai 2019: Manchmal ist die "hässliche" mehrzeilige Zeichenfolge wirklich der beste Weg!

Also habe ich Python verwendet, um C-Header- und Quelldateien (.h / .c) automatisch aus textbasierten Konfigurationsdateien zu generieren , und nachdem ich eine ganze Menge davon getan habe, bin ich zu dem Schluss gekommen, dass die Vorteile des einfachen Kopierens Das Einfügen großer Textblöcke aus einer Konfigurationsdatei in mein Python-Skript überwiegt alle "Hässlichkeits" -Faktoren.

Aus diesem Grund habe ich festgestellt, dass das Folgende meine bevorzugte Methode ist, wenn beispielsweise eine große, mehrzeilige, kopierte Zeichenfolge erforderlich ist:

Option 1:

  • Verwenden Sie Klammern um die gesamte lange Zeichenfolge, damit sich die Öffnung """in einer neuen Zeile befindet

    Holen Sie sich einige Einrückungsstufen, um immer noch den "Hässlichkeit" -Effekt zu zeigen.

    if (True): if (True): if (True): header = ("" "/ * meine benutzerdefinierten Datei-Header-Informationen hier * /

    #pragma einmal

    #include "{}"

    const {} {}; "" ") .format (include, struct_t, struct)

              print("header =" + header)
    

Option 2:

  • Keine Klammer, aber das Schließen """in eine eigene Zeile setzen

    Holen Sie sich einige Einrückungsstufen, um immer noch den "Hässlichkeit" -Effekt zu zeigen.

    if (True): if (True): if (True): header = "" "/ * meine benutzerdefinierten Datei-Header-Informationen hier * /

    #pragma einmal

    #include "{}"

    const {} {}; "" ".format (include, struct_t, struct)

              print("header =" + header)
    

Option 3:

  • Keine Klammern um die gesamte Zeichenfolge, und setzen Sie den Abschluss """in dieselbe Zeile wie den Inhalt der Zeichenfolge, um zu verhindern, dass \nam Ende eine (möglicherweise unerwünschte) hinzugefügt wird .

  • Setzen Sie den Rest von jedoch format(in eine neue Zeile (oder in viele neue Zeilen), falls diese lang ist.

    Holen Sie sich einige Einrückungsstufen, um immer noch den "Hässlichkeit" -Effekt zu zeigen.

    if (True): if (True): if (True): header = "" "/ * meine benutzerdefinierten Datei-Header-Informationen hier * /

    #pragma einmal

    #include "{}"

    const {} {}; "" ". format (include, struct_t, struct) # Einrückung hier kann buchstäblich alles sein , aber ich mag es, 1 Ebene einzurücken, da es in Klammern steht, spielt es jedoch keine Rolle

              print("header =" + header)
    

Ausgabe:

  • Die Optionen 1 und 2 erzeugen eine genau identische Ausgabe mit einem Extra \nam Ende der Zeichenfolge, was in den meisten Fällen in Ordnung ist
  • Option 3 erzeugt dieselbe exakte Ausgabe wie Option 1 und 2, außer dass sie nicht das Extra \nam Ende der Zeichenfolge enthält, falls dies für Ihren Fall unerwünscht ist
  • Ob Sie Option 1, 2 oder 3 verwenden, spielt wirklich keine Rolle - es ist an dieser Stelle nur die Benutzerpräferenz, abgesehen von dem \noben erwähnten Extra

Dies wird in den obigen Optionen 1, 2 und 3 gedruckt:

/*
my custom file header info here
*/

#pragma once

#include "<stdint.h>"

const my_struct_t my_struct;


ZUSAMMENSTELLEN: Eine Mischung aus "hübschen" und "hässlichen" Methoden, um das beste Ergebnis in dieser Demo zum Drucken von Dokumentationsdokumentationen für Ihr Modul zu erzielen !

Hier ist ein grundlegendes Beispiel für die Verwendung der oben vorgestellten "hübschen" und "hässlichen" mehrzeiligen Zeichenfolgenmethoden, um die jeweils besten Vorteile zu erzielen. Dies zeigt auch, wie Sie das Modul "docstrings" verwenden und drucken, um Ihr Modul zu dokumentieren. Beachten Sie, dass die """mehrzeilige Technik auf der Basis einen großen Abstand bietet, da \nnach dem Öffnen """und vor dem Schließen eine automatische Zeilenumbruch ( ) angezeigt wird , """da die Zeichenfolge so geschrieben wird.

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

Ausgabe:
- Beachten Sie, wie hübsch und gut formatiert alles automatisch ist, da die Registerkarten, Zeilenumbrüche und Abstände Ihrer Dokumentzeichenfolgen automatisch beibehalten werden, wenn Sie sie auf diese Weise drucken!

  
########################  
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  
          
  

Verweise:

  1. Python-Dokumentzeichenfolgen: https://www.geeksforgeeks.org/python-docstrings/
  • Hinweis: Sie können die help()Methode auch verwenden , um auf die Dokumentation eines Moduls oder einer Klasse zuzugreifen (jedoch auf interaktive Weise ), wie im obigen Link gezeigt:

         help(Math)  # to interactively display Class docstring
         help(Math.add)  # to interactively display method's docstring 
    
Gabriel Staples
quelle
4

Um die Argumente in derselben Zeile zu haben, in die sie eingefügt werden, können Sie dies folgendermaßen tun:

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

[EDIT:] Als Antwort auf den ersten Kommentar habe ich mir Folgendes ausgedacht:

cmd = "\n".join([
      "line %d"%1,
      "line %d"%2,
      "line %d"%3])
Qlaus
quelle
Dies mit mehr als 30 Argumenten zu tun, wäre nicht sehr effizient. "".join()auf einer Liste andererseits ... :)
Frédéric Hamidi
3

Sie können verwenden textwrap.dedent, um führende Leerzeichen aus Zeilen zu entfernen:

import textwrap

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

Das führt zu:

line 1
    line with indent
line 2
line 3
George Sovetov
quelle
Bitte stimmen Sie ab, diejenigen, die PyCharm verwenden: youtrack.jetbrains.com/issue/PY-34646 . Was die automatische Formatierung und die Regeln für die Formatierungsprüfung bewirken, ist im Snippet in der Frage nicht konsistent.
George Sovetov
2

Das funktioniert bei mir:

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

TLDR;

Springe gerade nach unten und schaue dir die Beispiele 1 und 4 unten an.

Vollständige Antwort:

Ich habe letzte Woche (Oktober 2020) kaum etwas über das Python- textwrapModul mit seiner wirklich praktischen textwrap.dedent()Funktion gelernt , und da es seit Python 2.7 existiert , kann ich nicht glauben, dass es nicht beliebter ist!

Die Verwendung textwrap.dedent()eines mehrzeiligen Strings löst alle Probleme meiner vorherigen Antwort !

Hier ist die offizielle Dokumentation dazu (Hervorhebung hinzugefügt):

textwrap.dedent(text)

Entfernen Sie alle gemeinsamen führenden Leerzeichen aus jeder Textzeile.

Dies kann verwendet werden, um Zeichenfolgen in dreifachen Anführungszeichen am linken Rand der Anzeige auszurichten und sie dennoch im Quellcode in eingerückter Form darzustellen.

Beachten Sie, dass Tabulatoren und Leerzeichen sowohl als Leerraum behandelt werden, aber sie sind nicht gleich: die Linien " hello"und "\thello"sind keine gemeinsame führende Leerzeichen haben , in Betracht gezogen.

Zeilen, die nur Leerzeichen enthalten, werden in der Eingabe ignoriert und in der Ausgabe auf ein einzelnes Zeilenumbruchzeichen normalisiert.

Zum Beispiel:

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'

Für alle Beispiele

import textwrap

Beispiel 1

Also, statt dies als die meist upvoted Antwort Staaten (dies verliert den schönen, sauberer, Einzug):

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

print(cmd)

Tun Sie dies (und BEHALTEN Sie die schöne, saubere Einkerbung)!

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

print(cmd)

Beispiel 2

Wenn Sie viele Argumente für die format()Funktion haben, können Sie diese bei Bedarf in mehrere Zeilen einfügen. Beachten Sie, dass die format()Argumente hier zwei Zeilen umfassen:

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)

Und wenn die format()Argumente wirklich lang sind, können Sie natürlich auch jedes Argument in eine eigene Zeile setzen:

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)

Beispiel 3

Und stattdessen , wie ich in meiner ursprünglichen Antwort angegeben habe (die gut aussehende Einrückungen beibehält, aber etwas mühsam zu verwenden ist):

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

... das kannst du jetzt machen! --womit meine mehrzeiligen Zeichenfolgen beim Drucken "am linken Rand des Displays ausgerichtet werden können, während sie im Quellcode in eingerückter Form angezeigt werden" (siehe offizielle Dokumentation ):

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

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

Beispiel 4

Und stattdessen , das mittendrin einen hässlich aussehenden Mangel an Einrückung aufweist:

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

... tun Sie dies , textwrap.dedent()um durchgehend gut aussehende Einrückungen zu erhalten!:

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

Führen Sie den obigen Code aus

Sie können meinen Testcode oben in meinem eRCaGuy_hello_world GitHub-Repo hier ausführen : textwrap_practice_1.py .

Führen Sie den Befehl aus:

./textwrap_practice_1.py

ODER:

python3 textwrap_practice_1.py
Gabriel Staples
quelle
1

Hier ist die einfachste Version, die auch hinsichtlich der Überprüfung von formatArgumenten IDE-freundlich ist :

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

Version mit mehrzeiligen Argumenten:

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',
    )
)
George Sovetov
quelle
Bitte stimmen Sie ab, diejenigen, die PyCharm verwenden: youtrack.jetbrains.com/issue/PY-34646 . Die automatische Formatierung und die Formatierungsprüfung sind im Snippet in der Frage nicht konsistent.
George Sovetov