Wie verwende ich Newline '\ n' in F-String, um die Ausgabe in Python 3.6 zu formatieren?

102

Ich würde gerne wissen, wie man diesen Fall pythonisch mit F-Strings formatiert:

names = ['Adam', 'Bob', 'Cyril']
text = f"Winners are:\n{'\n'.join(names)}"
print(text)

Das Problem ist, dass '\'es nicht innerhalb der {...}Ausdrucksteile eines F-Strings verwendet werden kann. Erwartete Ausgabe:

Winners are:
Adam
Bob
Cyril
malmed
quelle
10
f"Winners are:\n{chr(10).join(names)}"
wim

Antworten:

115

Das kannst du nicht. Backslashes können nicht in den geschweiften Klammern erscheinen {}. dies führt zu einem SyntaxError:

>>> f'{\}'
SyntaxError: f-string expression part cannot include a backslash

Dies ist im PEP für F-Strings angegeben:

Backslashes erscheinen möglicherweise nicht in den Ausdrucksteilen von F-Strings. [...]

Eine Möglichkeit besteht darin '\n', einen Namen und dann .joindiesen innerhalb der fZeichenfolge zuzuweisen. das heißt, ohne ein Literal zu verwenden:

names = ['Adam', 'Bob', 'Cyril']
nl = '\n'
text = f"Winners are:{nl}{nl.join(names)}"
print(text)

Ergebnisse in:

Winners are:
Adam
Bob
Cyril

Eine andere Option, wie von @wim angegeben, besteht chr(10)darin, \nzurückgegeben zu werden und dort beizutreten.f"Winners are:\n{chr(10).join(names)}"

Ein weiterer Grund ist natürlich, '\n'.joinvorher den Namen entsprechend hinzuzufügen:

n = "\n".join(names)
text = f"Winners are:\n{n}"

was zu der gleichen Ausgabe führt.

Hinweis:

Dies ist einer der kleinen Unterschiede zwischen f-strings und str.format. In letzterem Fall können Sie immer Interpunktion verwenden, vorausgesetzt, dass ein entsprechendes verrücktes Diktat entpackt wird, das die folgenden Schlüssel enthält:

>>> "{\\} {*}".format(**{"\\": 'Hello', "*": 'World!'})
"Hello World!"

(Bitte tu das nicht.)

Im ersten Fall ist die Interpunktion nicht zulässig, da Sie keine Bezeichner haben können, die sie verwenden.


Nebenbei: Ich würde mich definitiv für printoder entscheiden format, wie die anderen Antworten als Alternative vorschlagen. Die von mir angegebenen Optionen gelten nur, wenn Sie müssen aus irgendeinem Grund Verwendung f-Strings.

Nur weil etwas neu ist, heißt das nicht, dass du versuchen solltest, alles damit zu machen ;-)

Dimitris Fasarakis Hilliard
quelle
53

Sie benötigen keine F-Strings oder andere Formatierer, um eine Liste von Strings mit einem Trennzeichen zu drucken. Verwenden Sie einfach das sepSchlüsselwortargument, um print():

names = ['Adam', 'Bob', 'Cyril']
print('Winners are:', *names, sep='\n')

Ausgabe:

Winners are:
Adam
Bob
Cyril

Das heißt, die Verwendung von str.join()/str.format() here wäre wohl einfacher und lesbarer als jede F-String-Problemumgehung:

print('\n'.join(['Winners are:', *names]))
print('Winners are:\n{}'.format('\n'.join(names)))
Eugene Yarmash
quelle
13
Beste Antwort bisher. Ich verwende heutzutage die ganze Zeit das Auspacken von Sternen in der Druckfunktion, um einen Blick in ein Objekt zu werfen, z . B. print(*dir(some_object), sep='\n')oder print(*vars(some_object), sep='\n').
Rick unterstützt Monica
1
Was tun Sie, wenn Sie die Liste nicht direkt drucken möchten, z. B. wenn Sie sie an einen Logger übergeben?
Bob
1
@bob: dann benutze einfach str.join(): text = '\n'.join(['Winners are:', *names]). Übrigens, print()kann zum Schreiben in eine beliebige Datei verwendet werden ( standardmäßig mit dem fileArgument angegeben sys.stdout).
Eugene Yarmash
9

Sie können keine Backslashes in F-Strings verwenden, wie andere gesagt haben, aber Sie können dies mit umgehen os.linesep(obwohl dies nicht \nauf allen Plattformen möglich ist und nur empfohlen wird, wenn Binärdateien gelesen / geschrieben werden; siehe Ricks Kommentare):

>>> import os
>>> names = ['Adam', 'Bob', 'Cyril']
>>> print(f"Winners are:\n{os.linesep.join(names)}")
Winners are:
Adam
Bob
Cyril 

Oder vielleicht weniger lesbar, aber garantiert \n mit chr():

>>> print(f"Winners are:\n{chr(10).join(names)}")
Winners are:
Adam
Bob
Cyril
Chris_Rands
quelle
2
War ich nicht, aber das Verwenden os.linesepist keine gute Idee beim Schreiben von Text.
Rick unterstützt Monica
1
@ RickTeachey Ich habe die Einschränkung bereits in Klammern hinzugefügt und einen alternativen Ansatz vorgeschlagen. Wie auch immer, das OP
druckt
Ich denke nicht, dass es wichtig ist. os.linesepdient nur zum Lesen oder Lesen und Schreiben im Binärmodus . Ich weiß, dass es in diesem Fall genauso funktionieren wird, aber es ist eine schlechte Angewohnheit, damit anzufangen. Aber nochmal: Ich war nicht die Gegenstimme. Die Einschränkung ist gut genug für mich. :)
Rick unterstützt Monica
7

Die anderen Antworten geben Ideen, wie das Zeilenumbruchzeichen in ein F-String-Feld eingefügt werden kann. Ich würde jedoch argumentieren, dass für das Beispiel, das das OP gegeben hat (was möglicherweise auf den tatsächlichen Anwendungsfall des OP hinweist oder nicht), keine dieser Ideen tatsächlich verwendet werden sollte.

Der Sinn der Verwendung von F-Strings besteht darin, die Lesbarkeit des Codes zu verbessern. Mit F-Strings können Sie nichts anfangen, was Sie nicht tun können format. Überlegen Sie genau, ob dies besser lesbar ist (wenn Sie es könnten):

f"Winners are:\n{'\n'.join(names)}"

...oder dieses:

newline = '\n'
f"Winners are:\n{newline.join(names)}"

...oder dieses:

"Winners are:\n{chr(10).join(names)}"

gegen dieses:

"Winners are:\n{}".format('\n'.join(names))

Der letzte Weg ist mindestens genauso lesbar, wenn nicht mehr.

Kurz gesagt: Verwenden Sie keinen Hammer, wenn Sie einen Schraubendreher benötigen, nur weil Sie einen glänzenden neuen haben. Code wird viel häufiger gelesen als geschrieben.

Für andere Anwendungsfälle ist es möglich, dass die chr(10)Idee oder newlineIdee angemessen ist. Aber nicht für den Gegebenen.

Rick unterstützt Monica
quelle
7
Die Lesbarkeit ist subjektiv :) ... alte Praktiken passen zu Fachleuten und können in einigen Fällen besser lesbar sein, aber für Noobs fast unbekannt und daher für sie unlesbar sein. Entschuldigung für den philosophischen Standpunkt.
Malmed
2
@malmed Lesbarkeit ist im Allgemeinen nicht subjektiv. In diesem Fall definitiv nicht. Aber es lohnt sich nicht, lange darüber zu streiten.
Rick unterstützt Monica
@malmed Sie haben Recht, dass Lesbarkeit "subjektiv" in dem Sinne ist, dass sie durch vorherige Erfahrung trainiert werden kann. Da unser Gehirn und unsere Sinne Einschränkungen aufweisen, kann die Lesbarkeit objektiv daran gemessen werden, wie einfach es ist, den relevanten Text zu scannen, wie oft das menschliche Gehirn dazu neigt, ihn korrekt mit Mustern abzugleichen, und wie korrekt es auf unsere Gehirnvorhersagen über andere hinweist Code (einschließlich des Anfangs einer Anweisung / Zeile, die angibt, wie das Ende aussehen wird) und wie schnell er für einen Anfänger besser lesbar wird.
mtraceur