Jak użyć znaku nowej linii „\ n” w f-string, aby sformatować dane wyjściowe w Pythonie 3.6?

123

Chciałbym wiedzieć, jak sformatować ten przypadek w Pythonie za pomocą f-stringów:

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

Problem polega na tym, że '\'nie można go używać wewnątrz {...}fragmentów wyrażenia ciągu f. Oczekiwany wynik:

Winners are:
Adam
Bob
Cyril
malmed
źródło
11
f"Winners are:\n{chr(10).join(names)}"
wim

Odpowiedzi:

135

Nie możesz. Wewnątrz nawiasów klamrowych nie mogą pojawić się ukośne ukośne {}; spowoduje to SyntaxError:

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

Jest to określone w PEP dla f-stringów:

Ukośniki odwrotne mogą nie pojawiać się wewnątrz fragmentów wyrażenia f-stringów, [...]

Jedną z opcji jest przypisanie '\n'nazwy, a następnie .joinumieszczenie jej wewnątrz f-string; to znaczy bez użycia literału:

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

Prowadzi do:

Winners are:
Adam
Bob
Cyril

Inną opcją, określone przez @wim, jest użycie chr(10)aby \npowrócił, a potem przystąpić tam.f"Winners are:\n{chr(10).join(names)}"

Jeszcze innym jest oczywiście '\n'.joinwcześniejsze dodanie nazwy:

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

co daje taki sam wynik.

Uwaga:

To jedna z małych różnic między f-strings i str.format. W tym drugim przypadku zawsze możesz użyć interpunkcji, pod warunkiem, że zostanie rozpakowany odpowiedni zwariowany dykt, który zawiera te klucze:

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

(Proszę, nie rób tego.)

W pierwszym przypadku interpunkcja nie jest dozwolona, ​​ponieważ nie możesz mieć identyfikatorów, które ich używają.


Poza tym: zdecydowanie wybrałbym printlub format, jak sugerują inne odpowiedzi, jako alternatywę. Opcje, które podałem, mają zastosowanie tylko wtedy, gdy z jakiegoś powodu musisz użyć f-stringów.

To, że coś jest nowe, nie oznacza, że ​​powinieneś próbować i robić z tym wszystko ;-)

Dimitris Fasarakis Hilliard
źródło
56

Nie potrzebujesz f-stringów ani innych elementów formatujących, aby wydrukować listę ciągów z separatorem. Po prostu użyj separgumentu słowa kluczowego, aby print():

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

Wynik:

Winners are:
Adam
Bob
Cyril

To powiedziawszy, użycie str.join()/str.format() tutaj byłoby prawdopodobnie prostsze i bardziej czytelne niż jakiekolwiek obejście f-string:

print('\n'.join(['Winners are:', *names]))
print('Winners are:\n{}'.format('\n'.join(names)))
Eugene Yarmash
źródło
13
Jak dotąd najlepsza odpowiedź. Obecnie używam rozpakowywania gwiazdy w funkcji drukowania cały czas, aby zajrzeć do wnętrza jakiegoś obiektu, np . print(*dir(some_object), sep='\n')Lub print(*vars(some_object), sep='\n').
Rick wspiera Monikę
1
Co zrobić, jeśli nie chcesz drukować listy bezpośrednio, np. Przekazując ją do loggera?
bob
1
@bob: wtedy po prostu użyć str.join(): text = '\n'.join(['Winners are:', *names]). BTW, print()może służyć do zapisywania do dowolnego pliku ( domyślnie określony fileargumentem sys.stdout).
Eugene Yarmash
11

Nie możesz używać odwrotnych ukośników w f-stringach, jak powiedzieli inni, ale możesz obejść to za pomocą os.linesep(chociaż pamiętaj, że nie będzie to \nna wszystkich platformach i nie jest zalecane, chyba że czytasz / zapisujesz pliki binarne; zobacz komentarze Ricka ):

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

A może w mniej czytelny sposób, ale gwarantowany \n, z chr():

>>> print(f"Winners are:\n{chr(10).join(names)}")
Winners are:
Adam
Bob
Cyril
Chris_Rands
źródło
2
Nie ja, lecz stosując os.linesepto nie jest dobry pomysł podczas pisania tekstu.
Rick wspiera Monikę
1
@RickTeachey Dodałem już zastrzeżenie w nawiasach i zasugerowałem alternatywne podejście. W każdym razie OP drukuje na ekranie, nie zapisuje do pliku otwartego w trybie tekstowym
Chris_Rands
Myślę, że to nie ma znaczenia. os.linesepsłuży tylko do czytania lub czytania i pisania w trybie binarnym . Wiem, że w tym przypadku będzie działać tak samo, ale zaczynanie jest złym nawykiem. Ale znowu: nie byłem przeciw. To zastrzeżenie jest dla mnie wystarczająco dobre. :)
Rick wspiera Monikę
7

Inne odpowiedzi dają pomysły, jak umieścić znak nowej linii w polu f-string. Jednak argumentowałbym, że na przykład podany w PO (który może, ale nie musi wskazywać na faktyczny przypadek użycia PO), żaden z tych pomysłów nie powinien być faktycznie wykorzystywany.

Cały sens używania f-stringów polega na zwiększeniu czytelności kodu. Nie ma nic, co możesz zrobić z f-stringami, z którymi nie możesz zrobić format. Zastanów się dokładnie, czy jest coś bardziej czytelnego na ten temat (jeśli możesz to zrobić):

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

...albo to:

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

...albo to:

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

w porównaniu z tym:

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

Ostatni sposób jest co najmniej tak samo czytelny, jeśli nie bardziej.

Krótko mówiąc: nie używaj młotka, gdy potrzebujesz śrubokręta tylko dlatego, że masz nowy, błyszczący. Kod jest czytany znacznie częściej niż jest pisany.

W innych przypadkach użycia tak, jest możliwe, że chr(10)pomysł lub newlinepomysł będzie odpowiedni. Ale nie dla podanego.

Rick wspiera Monikę
źródło
7
Czytelność jest subiektywna :) ... stara praktyka jest odpowiednia dla wprawnych i może być bardziej czytelna w niektórych przypadkach, ale może być prawie nieznana noobom, a przez to dla nich nieczytelna. Przepraszam za filozoficzny punkt widzenia.
malmed
2
@malmed Czytelność generalnie nie jest subiektywna. Na pewno nie w tym przypadku. Ale nie warto się o to długo kłócić.
Rick wspiera Monikę
1
@malmed Masz rację, że czytelność jest „subiektywna” w tym sensie, że można ją trenować na podstawie wcześniejszego doświadczenia. Ale ponieważ nasze mózgi i zmysły mają ograniczenia, czytelność można obiektywnie zmierzyć w kategoriach tego, jak fizycznie łatwo jest zeskanować odpowiedni tekst, jak często ludzkie mózgi mają tendencję do prawidłowego dopasowywania go do wzorców, jak poprawnie wskazuje na przewidywania naszego mózgu dotyczące innych kod (w tym początek instrukcji / linii wskazującej, jaki będzie koniec) i jak łatwo staje się bardziej czytelny dla nowicjusza.
mtraceur