Bagaimana cara menggunakan baris baru '\ n' dalam f-string untuk memformat keluaran dengan Python 3.6?

122

Saya ingin tahu bagaimana memformat case ini dengan cara Pythonic dengan f-string:

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

Masalahnya adalah itu '\'tidak bisa digunakan di dalam {...}bagian ekspresi f-string. Output yang diharapkan:

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

Jawaban:

134

Tidak boleh. Garis miring terbalik tidak bisa muncul di dalam kurung kurawal {}; melakukan hal itu menghasilkan SyntaxError:

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

Ini ditentukan dalam PEP untuk f-string:

Garis miring terbalik mungkin tidak muncul di dalam bagian ekspresi f-string, [...]

Salah satu pilihan adalah '\n'memasukkan nama dan kemudian memilih .joindi dalam f-string; yaitu, tanpa menggunakan literal:

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

Hasil dalam:

Winners are:
Adam
Bob
Cyril

Opsi lain, sebagaimana ditentukan oleh @wim, adalah menggunakan chr(10)untuk \ndikembalikan dan kemudian bergabung di sana.f"Winners are:\n{chr(10).join(names)}"

Namun yang lainnya, tentu saja, adalah '\n'.jointerlebih dahulu dan kemudian menambahkan nama yang sesuai:

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

yang menghasilkan keluaran yang sama.

catatan:

Ini adalah salah satu perbedaan kecil antara f-string dan str.format. Yang terakhir, Anda selalu dapat menggunakan tanda baca yang diberikan bahwa dikt aneh yang sesuai dibongkar yang berisi kunci-kunci tersebut:

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

(Tolong jangan lakukan ini.)

Dahulu, tanda baca tidak diperbolehkan karena Anda tidak boleh memiliki pengenal yang menggunakannya.


Selain: Saya pasti akan memilih printatau format, seperti yang disarankan jawaban lain sebagai alternatif. Opsi yang saya berikan hanya berlaku jika Anda harus menggunakan f-string karena alasan tertentu.

Hanya karena ada sesuatu yang baru, bukan berarti Anda harus mencoba dan melakukan semuanya dengannya ;-)

Dimitris Fasarakis Hilliard
sumber
56

Anda tidak memerlukan f-string atau pemformat lain untuk mencetak daftar string dengan pemisah. Cukup gunakan separgumen kata kunci untuk print():

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

Keluaran:

Winners are:
Adam
Bob
Cyril

Karena itu, menggunakan str.join()/ distr.format() sini bisa dibilang lebih sederhana dan lebih mudah dibaca daripada solusi f-string apa pun:

print('\n'.join(['Winners are:', *names]))
print('Winners are:\n{}'.format('\n'.join(names)))
Eugene Yarmash
sumber
13
Jawaban terbaik sejauh ini. Saya menggunakan bintang membongkar dalam fungsi cetak sepanjang waktu hari ini untuk melihat ke dalam beberapa objek, misalnya print(*dir(some_object), sep='\n')atau print(*vars(some_object), sep='\n').
Rick mendukung Monica
1
Apa yang Anda lakukan jika Anda tidak ingin mencetak daftar secara langsung, misalnya jika Anda meneruskannya ke logger?
bob
1
@ Bob: maka cukup gunakan str.join(): text = '\n'.join(['Winners are:', *names]). BTW, print()dapat digunakan untuk menulis ke file apa pun (ditentukan dengan fileargumen, sys.stdoutsecara default).
Eugene Yarmash
11

Anda tidak dapat menggunakan garis miring terbalik di f-string seperti yang dikatakan orang lain, tetapi Anda dapat melangkah di sekitar ini menggunakan os.linesep(meskipun perhatikan ini tidak akan ada \ndi semua platform, dan tidak disarankan kecuali membaca / menulis file biner; lihat komentar Rick ):

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

Atau mungkin dengan cara yang kurang mudah dibaca, tetapi dijamin \n, dengan chr():

>>> print(f"Winners are:\n{chr(10).join(names)}")
Winners are:
Adam
Bob
Cyril
Chris_Rands
sumber
2
Bukan aku, tetapi menggunakan os.linesepadalah bukan ide yang baik saat menulis teks.
Rick mendukung Monica
1
@RickTeachey Saya sudah menambahkan peringatan dalam tanda kurung dan menyarankan pendekatan alternatif. Bagaimanapun, OP sedang mencetak ke layar, tidak menulis ke file yang dibuka dalam mode teks
Chris_Rands
Saya tidak berpikir itu penting. os.linesephanya untuk membaca, atau membaca dan menulis dalam mode biner . Saya tahu itu akan bekerja sama dalam kasus ini, tetapi itu adalah kebiasaan buruk untuk memulai. Tapi sekali lagi: Saya bukan orang yang tidak disukai. Peringatan itu cukup bagus untuk saya. :)
Rick mendukung Monica
7

Jawaban lain memberikan ide bagaimana menempatkan karakter baris baru ke dalam bidang f-string. Namun, saya berpendapat bahwa untuk contoh yang diberikan OP (yang mungkin atau mungkin tidak merupakan indikasi kasus penggunaan OP yang sebenarnya), tidak satu pun dari gagasan ini yang benar-benar harus digunakan.

Inti dari penggunaan f-string adalah meningkatkan keterbacaan kode. Tidak ada yang dapat Anda lakukan dengan f-string yang tidak dapat Anda lakukan format. Pertimbangkan baik-baik apakah ada yang lebih bisa dibaca tentang ini (jika Anda bisa melakukannya):

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

...atau ini:

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

...atau ini:

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

vs. ini:

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

Cara terakhir setidaknya dapat dibaca, jika tidak lebih.

Singkatnya: jangan gunakan palu saat Anda membutuhkan obeng hanya karena Anda memiliki obeng baru yang mengkilap. Kode dibaca lebih sering daripada yang tertulis.

Untuk kasus penggunaan lain, ya, mungkin saja chr(10)ide atau newlineidenya sesuai. Tapi tidak untuk yang diberikan.

Rick mendukung Monica
sumber
7
Keterbacaan itu subjektif :) ... praktik lama cocok untuk yang terampil dan dapat lebih mudah dibaca dalam beberapa kasus, tetapi hampir tidak diketahui oleh pemula dan karenanya tidak dapat dibaca oleh mereka. Maaf untuk sudut pandang filosofis.
malmed
2
@malmed Readability umumnya tidak subjektif. Jelas tidak dalam kasus ini. Tapi tidak ada gunanya berdebat panjang lebar.
Rick mendukung Monica
1
@malmed Anda benar bahwa keterbacaan itu "subyektif" dalam arti dapat dilatih oleh pengalaman sebelumnya. Tetapi karena otak dan indera kita memiliki keterbatasan, keterbacaan dapat diukur secara obyektif dalam hal seberapa mudah secara fisik untuk memindai teks yang relevan, seberapa sering otak manusia cenderung menyesuaikan pola dengan benar, seberapa benar itu mengisyaratkan prediksi otak kita tentang teks lain. kode (termasuk awal pernyataan / baris yang mengisyaratkan apa akhirnya), dan seberapa mudah itu menjadi lebih mudah dibaca oleh seorang pemula.
mtraceur