Як використовувати новий рядок \ \ n у f-string для форматування виводу в Python 3.6?


109

Я хотів би знати, як відформатувати цей випадок пітонічним способом за допомогою f-рядків:

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

Проблема в тому, що '\'не можна використовувати всередині {...}частин виразу f-рядка. Очікуваний результат:

Winners are:
Adam
Bob
Cyril

10
f"Winners are:\n{chr(10).join(names)}"
вім

Відповіді:


123

Ви не можете. Поворотні риски не можуть з’являтися всередині фігурних дужок {}; це призводить до SyntaxError:

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

Це вказано в PEP для f-рядків:

Зворотні скісні риски можуть не відображатися всередині частин виразу f-рядків, [...]

Одним із варіантів є присвоєння '\n'імені, а потім .joinвсередині f-string; тобто без використання літералу:

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

Призводить до:

Winners are:
Adam
Bob
Cyril

Інший варіант, як зазначено @wim, полягає у використанні chr(10)для \nповернення, а потім приєднання до нього.f"Winners are:\n{chr(10).join(names)}"

Ще одне, звичайно, це '\n'.joinзаздалегідь, а потім відповідно додати назву:

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

що призводить до того ж результату.

Примітка:

Це одна з невеликих відмінностей між f-strings та str.format. В останньому випадку ви завжди можете використовувати розділові знаки, які дозволяють розпакувати відповідний дурний дикт, що містить такі ключі:

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

(Будь ласка, не робіть цього.)

У першій пунктуація заборонена, оскільки ви не можете мати ідентифікатори, які їх використовують.


Окрім: я б точно вибрав printабо format, як пропонують інші відповіді як альтернативу. Варіанти, які я надав, застосовуються лише в тому випадку, якщо з якихось причин ви повинні використовувати f-рядки.

Те, що щось нове, не означає, що потрібно намагатися робити все з цим ;-)


55

Вам не потрібні f-рядки або інші форматори, щоб надрукувати список рядків із роздільником. Просто використовуйте sepаргумент ключового слова для print():

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

Вихід:

Winners are:
Adam
Bob
Cyril

Тим не менш, використання str.join()/str.format() тут, можливо, було б простішим і читабельнішим, ніж будь-яке обхідне рішення f-string:

print('\n'.join(['Winners are:', *names]))
print('Winners are:\n{}'.format('\n'.join(names)))

13
На сьогодні найкраща відповідь. У ці дні я весь час використовую розпакування зірок у функції друку, щоб заглянути всередину якогось об’єкта, наприклад print(*dir(some_object), sep='\n')або print(*vars(some_object), sep='\n').
Рік підтримує Моніку

1
Що робити, якщо ви не хочете друкувати список безпосередньо, наприклад, якщо ви передаєте його реєстратору?
боб

1
@bob: потім просто використовувати str.join(): text = '\n'.join(['Winners are:', *names]). BTW, print()може використовуватися для запису в будь-який файл ( за замовчуванням вказано з fileаргументом sys.stdout).
Євген Ярмаш

10

Ви не можете використовувати зворотні скісні риски у f-рядках, як казали інші, але ви можете обійти це за допомогою os.linesep(хоча зауважте, це буде не \nна всіх платформах і не рекомендується, якщо не читати / писати двійкові файли; див . Коментарі Ріка ):

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

Або, можливо, менш читабельним способом, але гарантовано \n, з chr():

>>> print(f"Winners are:\n{chr(10).join(names)}")
Winners are:
Adam
Bob
Cyril

2
Не я, але використання os.linesep- це не гарна ідея при написанні тексту.
Рік підтримує Моніку

1
@RickTeachey Я вже додав застереження в дужки і пропоную альтернативний підхід. У будь-якому випадку, ОП друкує на екран, а не записує у файл, відкритий у текстовому режимі
Chris_Rands

Я не думаю, що це має значення. os.linesepпризначений лише для читання або читання та запису у двійковому режимі . Я знаю, що в цьому випадку це спрацює так само, але починати це погана звичка. Але знову ж таки: я не був проти. Застереження досить добре для мене. :)
Рік підтримує Моніку

6

Інші відповіді дають ідеї щодо того, як помістити символ нового рядка у поле f-рядка. Однак я б стверджував, що для прикладу, наведеного ОП (який може або не може свідчити про фактичний випадок використання ОП), жодна з цих ідей насправді не повинна використовуватися.

Вся суть використання f-рядків - це збільшення читабельності коду. З f-рядками ви нічого не можете зробити, з чим не зможете format. Уважно розгляньте, чи є в цьому щось більш читабельне (якщо б ви могли це зробити):

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

... або це:

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

... або це:

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

проти цього:

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

Останній спосіб є принаймні настільки ж читабельним, якщо не більше.

Коротше кажучи: не використовуйте молоток, коли вам потрібна викрутка, лише тому, що у вас є блискуча нова. Код читається набагато частіше, ніж пишеться.

Для інших випадків використання, так, можливо, chr(10)ідея чи newlineідея можуть бути доречними. Але не для даного.


7
Читаність суб’єктивна :) ... стара практика підходить кваліфікованим і може бути більш читабельною в деяких випадках, але може бути майже невідомою для нубів і, отже, нечитабельною для них. Вибачте за філософську точку зору.
malmed

2
@malmed Читаність, як правило, не є суб'єктивною. У цьому випадку точно не. Але не варто довго сперечатися.
Рік підтримує Моніку

@malmed Ви маєте рацію, що читабельність є "суб'єктивною" в тому сенсі, що вона піддається навчанню за попереднім досвідом. Але оскільки наш мозок і органи чуття мають обмеження, читабельність можна об’єктивно виміряти з точки зору того, наскільки фізично легко відсканувати відповідний текст, як часто людський мозок має тенденцію правильно його співпадати, наскільки правильно він натякає на наші прогнози мозку щодо інших код (включаючи початок висловлювання / рядок, що натякає на те, яким буде кінець), і наскільки він стає легшим для читання початківцем.
mtraceur
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.