Bagaimana saya bisa memecah garis panjang ini dengan Python?

176

Bagaimana Anda akan memformat garis panjang seperti ini? Saya ingin membuatnya tidak lebih dari 80 karakter:

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

Apakah ini opsi terbaik saya?

url = "Skipping {0} because its thumbnail was already in our system as {1}."
logger.info(url.format(line[indexes['url']], video.title))
Gattster
sumber
1
Sepertinya pilihan yang bagus. Apa yang tidak Anda sukai tentang itu?
Hamish Grubijan
2
Sedikit subjektif, bukan? :)
Adam Woś
1
terkait: stackoverflow.com/questions/1940710/… (string concatenation in python)
jldupont
14
Anda dapat menyimpan karakter dengan menghapus yang salah 'di "itu".
jball
2
indexes: jamak yang benar indexadalah indices.
Scruffy

Jawaban:

336

Itu awal. Ini bukan praktik yang buruk untuk mendefinisikan string Anda yang lebih panjang di luar kode yang menggunakannya. Ini adalah cara untuk memisahkan data dan perilaku. Pilihan pertama Anda adalah menggabungkan string literal bersama secara implisit dengan membuatnya berdekatan satu sama lain:

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

Atau dengan kelanjutan akhir baris, yang sedikit lebih rapuh, karena ini berfungsi:

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

Tetapi ini tidak:

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

Lihat perbedaannya? Tidak? Baik Anda tidak akan ketika itu kode Anda juga.

Kelemahan dari penyatuan implisit adalah bahwa itu hanya bekerja dengan string literal, bukan dengan string yang diambil dari variabel, sehingga hal-hal bisa menjadi sedikit lebih berbulu ketika Anda refactor. Selain itu, Anda hanya dapat menginterpolasi pemformatan pada string gabungan secara keseluruhan.

Atau, Anda dapat bergabung secara eksplisit menggunakan operator gabungan ( +):

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

Eksplisit lebih baik daripada implisit, seperti kata zen dari python, tetapi ini menciptakan tiga string, bukan satu, dan menggunakan memori dua kali lebih banyak: ada dua yang telah Anda tulis, ditambah satu yang keduanya bergabung bersama, jadi Anda harus tahu kapan harus mengabaikan zen. Sisi baiknya adalah Anda dapat menerapkan pemformatan ke salah satu substring secara terpisah di setiap baris, atau ke seluruh lot dari luar tanda kurung.

Akhirnya, Anda dapat menggunakan string yang dikutip tiga kali lipat:

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

Ini sering menjadi favorit saya, meskipun perilakunya sedikit berbeda karena baris baru dan spasi putih mana pun pada baris berikutnya akan muncul di string terakhir Anda. Anda dapat menghilangkan baris baru dengan garis miring terbalik.

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

Ini memiliki masalah yang sama dengan teknik yang sama di atas, dalam kode yang benar hanya berbeda dari kode yang salah oleh spasi kosong.

Mana yang "terbaik" tergantung pada situasi khusus Anda, tetapi jawabannya bukan hanya estetika, tetapi salah satu perilaku yang agak berbeda.

jcdyer
sumber
26
Compiler CPython mengoptimalkan operasi literal sebanyak mungkin, yang berarti menambahkan dua string literal menghasilkan hanya string string tunggal dalam bytecode.
Ignacio Vazquez-Abrams
2
Meskipun semua jawaban yang saya terima sangat membantu, jawaban Anda pasti membantu saya memahami semua cara untuk memutuskan. Apakah masalah dengan baris "\" berakhir bahwa ada spasi setelahnya?
Gattster
1
Saya tidak bisa melihat perbedaannya di sini, tetapi kemudian, itu sebagian besar karena pewarnaan sintaksis yang agak primitif. (Beberapa kode yang sangat bagus sebenarnya hampir tidak dapat dibaca di SO, tetapi hanya karena itu tidak dalam bahasa yang sintaksinya sangat dekat dengan C.) Bukan hal aneh untuk membuat editor Anda secara tidak sengaja menyoroti spasi tambahan, karena jarang berguna (atau disengaja) . :-)
Ken
1
@KhurshidAlam Anda bisa menggunakan tanda kutip tunggal 'untuk memuat string itu, atau keluar dari tanda kutip ganda di dalam string Anda, atau menggunakan tanda kutip ganda rangkap """. Masalah dengan string kutipan yang berisi kutipan adalah sama apakah Anda menggunakan satu baris atau beberapa baris untuk mendefinisikan string literal.
hugovdberg
1
Editor saya selalu menghapus spasi spasi tambahan. Saya sarankan Anda mengaktifkan pengaturan yang sama. Tentu saja spasi putih pada baris baru masih menjadi bagian dari string, jadi saya akhirnya menggunakan +.
ThaJay
46

Literal string berturut-turut digabungkan oleh kompiler, dan ekspresi yang diurung dianggap sebagai satu baris kode:

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

Secara pribadi saya tidak suka menggantung blok terbuka, jadi saya memformatnya sebagai:

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

Secara umum saya tidak akan repot-repot berjuang terlalu keras untuk membuat kode pas persis dalam garis 80-kolom. Sebaiknya menjaga panjang garis ke tingkat yang wajar, tetapi batas 80 sulit adalah sesuatu dari masa lalu.

bobince
sumber
8
Ini bukan benar-benar masa lalu. Pustaka standar Python masih menggunakan PEP8 sebagai panduan gayanya, jadi aturannya masih ada, dan banyak orang (termasuk saya) mengikutinya. Ini adalah tempat yang nyaman untuk menggambar garis.
Devin Jeanpierre
3
Saya bertanya-tanya berapa banyak proyek yang masih mengikuti aturan 80 char. Untuk ukuran jendela rata-rata yang saya gunakan, saya pikir 100-120 lebih produktif untuk saya daripada 80 karakter.
Gattster
1
Ya, itu tentang panjang garis yang saya gunakan juga, [horor! sacrilege!] Saya menggunakan font proporsional, jadi panjang garis yang tepat tidak terlalu kritis. Ini lebih merupakan kasus dari seberapa banyak logika pada satu baris dapat dibaca daripada berapa banyak karakter, dengan demikian ... jika saya punya string data yang panjang yang tidak perlu dibaca, saya senang membiarkannya tumpah 120.
bobince
Font yang proporsional untuk kode - Saya bersamamu, saudara. Dihakimi oleh ketidaksukaan yang dimiliki semua orang yang pernah bekerja dengan saya untuk mereka, dunia tidak siap.
jlarcombe
4
~ 80 karakter juga memudahkan untuk membedakan 2 file berdampingan pada layar yang sama. Juga, jika Anda men-debug sesuatu selama keadaan darurat yang mengerikan di konsol server Anda akan sangat menghargai batas 80 karakter! :)
Mick T
4

Anda dapat menggunakan modul textwrap untuk memecahnya dalam beberapa baris

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

ABCDEFGH
IJKLIMNO

Dari dokumentasi :

penulisan teks. wrap (text [, width [, ...]])
Membungkus paragraf tunggal dalam teks (string) sehingga setiap baris paling panjang karakternya. Mengembalikan daftar jalur keluaran, tanpa baris baru final.

Argumen kata kunci opsional sesuai dengan atribut instance TextWrapper, yang didokumentasikan di bawah ini. lebar default ke 70.

Lihat TextWrapper.wrap()metode untuk detail tambahan tentang bagaimana wrap () berperilaku.

Saurabh
sumber
2

Bagi siapa saja yang juga mencoba untuk memanggil .format()pada tali panjang, dan tidak dapat menggunakan beberapa teknik tali pembungkus paling populer tanpa melanggar berikutnya .format(panggilan, Anda dapat melakukan str.format("", 1, 2)bukan "".format(1, 2). Ini memungkinkan Anda memecahkan tali dengan teknik apa pun yang Anda suka. Sebagai contoh:

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

dapat

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

Kalau tidak, satu-satunya kemungkinan adalah menggunakan lanjutan garis akhir, yang secara pribadi saya bukan penggemar.

Simon Alford
sumber