Wie kann ich diese lange Zeile in Python auflösen?

176

Wie würden Sie eine lange Zeile wie diese formatieren? Ich möchte, dass es nicht mehr als 80 Zeichen breit ist:

logger.info("Skipping {0} because its thumbnail was already in our system as {1}.".format(line[indexes['url']], video.title))

Ist das meine beste Option?

url = "Skipping {0} because its thumbnail was already in our system as {1}."
logger.info(url.format(line[indexes['url']], video.title))
Gattster
quelle
1
Scheint eine gute Option zu sein. Was magst du daran nicht?
Hamish Grubijan
2
Ein bisschen subjektiv, nicht wahr? :)
Adam Woś
1
Verwandte: stackoverflow.com/questions/1940710/… (String-Verkettung in Python)
jldupont
14
Sie können ein Zeichen speichern, indem Sie das falsche 'in "es" entfernen.
Jball
2
indexes: der richtige Plural von indexist indices.
Scruffy

Antworten:

336

Das ist ein Anfang. Es ist keine schlechte Praxis, Ihre längeren Zeichenfolgen außerhalb des Codes zu definieren, der sie verwendet. Es ist eine Möglichkeit, Daten und Verhalten zu trennen. Ihre erste Option besteht darin, Zeichenfolgenliterale implizit miteinander zu verbinden, indem Sie sie nebeneinander platzieren:

("This is the first line of my text, "
"which will be joined to a second.")

Oder mit Fortsetzungen am Zeilenende, was etwas fragiler ist, da dies funktioniert:

"This is the first line of my text, " \
"which will be joined to a second."

Das geht aber nicht:

"This is the first line of my text, " \ 
"which will be joined to a second."

Sieh den Unterschied? Nein? Das wirst du auch nicht, wenn es dein Code ist.

Der Nachteil des impliziten Joinings besteht darin, dass es nur mit String-Literalen funktioniert, nicht mit Strings, die aus Variablen stammen. Daher können die Dinge beim Refactor etwas haariger werden. Außerdem können Sie die Formatierung nur für die gesamte kombinierte Zeichenfolge interpolieren.

Alternativ können Sie explizit mit dem Verkettungsoperator ( +) beitreten :

("This is the first line of my text, " + 
"which will be joined to a second.")

Explizit ist besser als implizit, wie der Zen von Python sagt, aber dies erzeugt drei Zeichenfolgen anstelle einer und verbraucht doppelt so viel Speicher: Es gibt die beiden, die Sie geschrieben haben, plus eine, bei der es sich um die beiden handelt, die miteinander verbunden sind, also Sie muss wissen, wann man den Zen ignoriert. Der Vorteil ist, dass Sie die Formatierung auf jede der Teilzeichenfolgen separat in jeder Zeile oder auf das gesamte Los von außerhalb der Klammern anwenden können.

Schließlich können Sie Zeichenfolgen in dreifachen Anführungszeichen verwenden:

"""This is the first line of my text
which will be joined to a second."""

Dies ist oft mein Favorit, obwohl sein Verhalten etwas anders ist, da die neue Zeile und alle führenden Leerzeichen in nachfolgenden Zeilen in Ihrer letzten Zeichenfolge angezeigt werden. Sie können den Zeilenumbruch mit einem Escape-Backslash entfernen.

"""This is the first line of my text \
which will be joined to a second."""

Dies hat das gleiche Problem wie die oben beschriebene Technik, da sich der richtige Code nur durch unsichtbare Leerzeichen vom falschen Code unterscheidet.

Welches "am besten" ist, hängt von Ihrer speziellen Situation ab, aber die Antwort ist nicht einfach ästhetisch, sondern eines von subtil unterschiedlichen Verhaltensweisen.

jcdyer
quelle
26
Der CPython-Compiler optimiert Literaloperationen so weit wie möglich, was bedeutet, dass das Hinzufügen von zwei Zeichenfolgenliteralen nur zu einem einzigen Zeichenfolgenliteral im Bytecode führt.
Ignacio Vazquez-Abrams
2
Obwohl alle Antworten, die ich erhalten habe, hilfreich sind, hilft mir Ihre definitiv dabei, alle Möglichkeiten zu verstehen, wie man Fäden aufbricht. War das Problem mit der Zeile "\", dass ein Leerzeichen dahinter stand?
Gattster
1
Ich kann den Unterschied hier nicht erkennen, aber das liegt hauptsächlich an der eher primitiven Syntaxfarbe von SO. (Einige vollkommen gute Codes sind auf SO praktisch nicht lesbar, aber nur, weil sie nicht in einer Sprache vorliegen, deren Syntax sehr nahe an C liegt.) Es ist nicht ungewöhnlich, dass Ihr Editor nachgestellte Leerzeichen unangenehm hervorhebt, da sie selten nützlich (oder absichtlich) sind. . :-)
Ken
1
@KhurshidAlam Sie können einfache Anführungszeichen verwenden ', um diese Zeichenfolge zu enthalten, oder die doppelten Anführungszeichen in Ihrer Zeichenfolge umgehen oder die dreifachen doppelten Anführungszeichen verwenden """. Das Problem mit Zeichenfolgen in Anführungszeichen, die Anführungszeichen enthalten, ist das gleiche, unabhängig davon, ob Sie eine einzelne Zeile oder mehrere Zeilen verwenden, um die Literalzeichenfolge zu definieren.
Hugovdberg
1
Mein Editor entfernt nachgestellte Leerzeichen immer. Ich empfehle Ihnen, die gleiche Einstellung zu aktivieren. Natürlich ist dann das Leerzeichen in der neuen Zeile immer noch Teil der Zeichenfolge, also habe ich es letztendlich verwendet +.
Donnerstag,
46

Aufeinanderfolgende Zeichenfolgenliterale werden vom Compiler zusammengefügt, und Ausdrücke in Klammern werden als einzelne Codezeile betrachtet:

logger.info("Skipping {0} because it's thumbnail was "
  "already in our system as {1}.".format(line[indexes['url']],
  video.title))
Ignacio Vazquez-Abrams
quelle
11

Persönlich mag ich es nicht, offene Blöcke aufzuhängen, also würde ich es wie folgt formatieren:

logger.info(
    'Skipping {0} because its thumbnail was already in our system as {1}.'
    .format(line[indexes['url']], video.title)
)

Im Allgemeinen würde ich mich nicht zu sehr darum bemühen, dass der Code genau in eine Zeile mit 80 Spalten passt. Es lohnt sich, die Leitungslänge auf einem vernünftigen Niveau zu halten, aber das harte 80-Limit gehört der Vergangenheit an.

Bobince
quelle
8
Es gehört nicht wirklich der Vergangenheit an. Die Python-Standardbibliothek verwendet weiterhin PEP8 als Styleguide, sodass die Regel weiterhin besteht und viele Personen (ich selbst eingeschlossen) ihr folgen. Es ist ein bequemer Ort, um die Grenze zu ziehen.
Devin Jeanpierre
3
Ich frage mich, wie viele Projekte noch der 80-Zeichen-Regel folgen. Für die durchschnittliche Fenstergröße, die ich verwende, denke ich, dass 100-120 für mich produktiver sind als 80 Zeichen.
Gattster
1
Ja, das ist ungefähr die Zeilenlänge, die ich auch benutze [Horror! Sakrileg!] Ich verwende eine proportionale Schriftart, daher ist die genaue Zeilenlänge nicht so kritisch. Es geht eher darum, wie viel Logik in einer einzelnen Zeile lesbar ist als wie viele Zeichen als solche ... Wenn ich eine lange Datenfolge habe, die niemand lesen muss, lasse ich sie gerne überlaufen 120.
Bobince
Proportionalschriftarten für Code - Ich bin bei dir, Bruder. Gemessen an der Abneigung, mit der jeder, mit dem ich jemals gearbeitet habe, für sie war, ist die Welt noch nicht bereit.
Jlarcombe
4
~ 80 Zeichen erleichtern es auch, zwei Dateien nebeneinander auf demselben Bildschirm zu verteilen. Wenn Sie während eines Notfalls auf der Konsole eines Servers etwas debuggen, werden Sie das Limit von 80 Zeichen wirklich zu schätzen wissen! :)
Mick T
4

Sie können das Textwrap-Modul verwenden, um es in mehrere Zeilen zu unterteilen

import textwrap
str="ABCDEFGHIJKLIMNO"
print("\n".join(textwrap.wrap(str,8)))

ABCDEFGH
IJKLIMNO

Aus der Dokumentation :

Textumbruch. wrap (text [, width [, ...]])
Umschließt den einzelnen Absatz mit Text (einer Zeichenfolge), sodass jede Zeile höchstens Zeichen breit ist. Gibt eine Liste der Ausgabezeilen ohne endgültige Zeilenumbrüche zurück.

Optionale Schlüsselwortargumente entsprechen den TextWrapperunten dokumentierten Instanzattributen von. Die Standardeinstellung ist width70 .

TextWrapper.wrap()Weitere Informationen zum Verhalten von wrap () finden Sie in der Methode.

Saurabh
quelle
2

Für alle, die auch versuchen, .format()eine lange Zeichenfolge aufzurufen , und einige der beliebtesten Techniken zum Umschließen von Zeichenfolgen nicht verwenden können, ohne den nachfolgenden .format(Aufruf zu unterbrechen, können Sie dies str.format("", 1, 2)stattdessen tun "".format(1, 2). Auf diese Weise können Sie die Saite mit einer beliebigen Technik brechen. Beispielsweise:

logger.info("Skipping {0} because its thumbnail was already in our system as {1}.".format(line[indexes['url']], video.title))

kann sein

logger.info(str.format(("Skipping {0} because its thumbnail was already"
+ "in our system as {1}"), line[indexes['url']], video.title))

Ansonsten besteht die einzige Möglichkeit darin, Fortsetzungen am Zeilenende zu verwenden, von denen ich persönlich kein Fan bin.

Simon Alford
quelle