Cara menulis string yang sangat panjang yang sesuai dengan PEP8 dan mencegah E501

203

Seperti PEP8 menyarankan untuk tetap di bawah aturan 80 kolom untuk program python Anda, bagaimana saya bisa mematuhinya dengan string panjang, yaitu

s = "this is my really, really, really, really, really, really, really long string that I'd like to shorten."

Bagaimana saya akan memperluas ini ke baris berikut, yaitu

s = "this is my really, really, really, really, really, really" + 
    "really long string that I'd like to shorten."
Federer
sumber

Jawaban:

116

Rangkaian implisit mungkin menjadi solusi terbersih:

s = "this is my really, really, really, really, really, really," \
    " really long string that I'd like to shorten."

Sunting Pada refleksi Saya setuju bahwa saran Todd untuk menggunakan tanda kurung daripada kelanjutan garis lebih baik untuk semua alasan yang dia berikan. Satu-satunya keraguan yang saya miliki adalah bahwa relatif mudah untuk mengacaukan string yang diberi tanda kurung dengan tuple.

Michael Dunn
sumber
4
Inilah sebabnya saya merasa seperti orang idiot yang mengirim pertanyaan. Bersulang.
Federer
8
Ini adalah kelanjutan garis dengan keluar dari garis akhir, bukan hanya gabungan implisit, dan sampai baru-baru ini secara eksplisit dilarang dalam PEP8, meskipun sekarang ada uang saku, tetapi BUKAN untuk string lama. Jawaban Todd di bawah ini benar.
Aaron Hall
4
Saya suka PEP8, tetapi ini adalah bagian dari PEP8 yang tidak saya sukai. Saya merasa kelanjutan implisit lebih jelas, karena kemungkinan kebingungan dengan tuple
monknomo
1
Ingatlah untuk tidak menambahkan spasi kosong setelah \
Mrinal Saurabh
bagaimana jika garis panjang di tengah-tengah string multi-garis panjang?
Thayne
299

Selain itu, karena konstanta string yang berdekatan secara otomatis digabungkan, Anda dapat mengkodekannya seperti ini juga:

s = ("this is my really, really, really, really, really, really, "  
     "really long string that I'd like to shorten.")

Catat tidak ada tanda tambah, dan saya menambahkan koma dan ruang tambahan yang mengikuti format contoh Anda.

Secara pribadi saya tidak suka garis miring terbalik, dan saya ingat pernah membaca di suatu tempat bahwa penggunaannya sebenarnya sudah tidak digunakan lagi dalam bentuk yang lebih eksplisit. Ingat "Eksplisit lebih baik daripada implisit."

Saya menganggap backslash kurang jelas dan kurang bermanfaat karena ini sebenarnya lolos dari karakter baris baru. Tidak mungkin untuk memberikan komentar akhir baris jika perlu. Dimungkinkan untuk melakukan ini dengan konstanta string gabungan:

s = ("this is my really, really, really, really, really, really, " # comments ok
     "really long string that I'd like to shorten.")

Saya menggunakan pencarian Google "panjang garis python" yang mengembalikan tautan PEP8 sebagai hasil pertama, tetapi juga tautan ke posting StackOverflow lain yang bagus tentang topik ini: " Mengapa Python PEP-8 menentukan panjang garis maksimum 79 karakter? "

Frasa pencarian bagus lainnya adalah "kelanjutan garis python".

Todd
sumber
8
+1: "Secara pribadi saya tidak suka garis miring terbalik, dan saya ingat pernah membaca di suatu tempat bahwa penggunaannya sebenarnya sudah tidak digunakan lagi dalam bentuk ini yang lebih eksplisit. Ingat" Eksplisit lebih baik daripada implisit. ""
Alberto Megía
13
Untuk semua orang yang mendapatkan tuple dan bertanya-tanya mengapa. Jangan tambahkan koma ke akhir baris di sini, yang akan menghasilkan tupel, bukan string. ;)
bugmenot123
7
Bukankah menambahkan karakter + lebih eksplisit dari contoh yang diberikan? Saya masih menganggap ini implisit. yaitu "str1" + "str2"daripada"str1" "str2"
user1318135
4
Saya sebenarnya setuju bahwa tanda plus lebih eksplisit, tetapi melakukan hal yang berbeda. Ini mengubah string menjadi ekspresi untuk dievaluasi, daripada menentukan konstanta string tunggal dalam sejumlah bagian. Saya tidak yakin tetapi saya pikir ini dilakukan selama parsing sedangkan ekspresi perlu dieksekusi nanti. Perbedaan kecepatan mungkin diabaikan kecuali ada sejumlah besar dari mereka. Tetapi juga secara estetika saya lebih suka penggabungan otomatis karena ini adalah satu karakter cluttery kurang per baris.
Todd
4
Sintaks ini juga menjaga kemungkinan menerapkan pemformatan string seperti:('this is my really, really, really, really, really long {} ' 'that I'd really, really, really, like to {}').format(var1, var2))
Tim
16

Saya pikir kata paling penting dalam pertanyaan Anda adalah "menyarankan".

Standar pengkodean adalah hal yang lucu. Seringkali pedoman yang mereka berikan memiliki dasar yang sangat bagus ketika ditulis (misalnya sebagian besar terminal tidak dapat menampilkan> 80 karakter pada satu baris), tetapi seiring berjalannya waktu mereka menjadi usang secara fungsional, tetapi masih dipegang teguh. Saya kira apa yang perlu Anda lakukan di sini adalah menimbang manfaat relatif dari "melanggar" saran khusus itu terhadap keterbacaan dan mainatinabilitas kode Anda.

Maaf ini tidak langsung menjawab pertanyaan Anda.

ZombieSheep
sumber
Saya sangat setuju. Ada aturan gaya Java serupa yang telah menjadi usang juga (IMHO).
Iker Jimenez
Ya saya setuju, namun sudah memutar kepala saya bagaimana saya akan mematuhinya dalam contoh khusus ini. Saya selalu mencoba mempertahankan kelas, metode hingga <80 karakter, namun saya katakan string seperti ini tidak memiliki efek selain yang negatif.
Federer
1
Anda juga perlu mempertimbangkan preferensi pribadi Anda terhadap standar pengkodean komunitas. Anda ingin orang baru dapat masuk dan merasa nyaman dengan pemformatan kode sejak hari pertama.
retracile
1
Saya tahu sendiri, saya cenderung untuk tetap pada batas 80 karakter hanya karena saya masih melakukan sebagian besar pengkodean saya di IDLE dan saya tidak suka cara menangani pengguliran horizontal. (Tidak ada bilah gulir)
Tofystedeth
@retracile - ya, benar. Saya tidak mengatakan "Anda harus mengabaikan pedoman", tetapi menyarankan bahwa dalam beberapa kasus pedoman tidak selalu ada untuk kebaikan masyarakat. Saya tidak mengetahui pembatasan IDLE (seperti yang diposting oleh Tofystedeth) tetapi dalam hal itu ada argumen keras untuk mengikuti konvensi.
ZombieSheep
13

Anda kehilangan spasi, dan Anda mungkin memerlukan karakter kelanjutan garis, yaitu. a \.

s = "this is my really, really, really, really, really, really" +  \
    " really long string that I'd like to shorten."

atau bahkan:

s = "this is my really, really, really, really, really, really"  \
    " really long string that I'd like to shorten."

Orang tua juga akan berfungsi sebagai ganti kelanjutan garis, tetapi Anda berisiko seseorang mengira Anda bermaksud memiliki tuple dan baru saja lupa koma. Ambil contoh:

s = ("this is my really, really, really, really, really, really"
    " really long string that I'd like to shorten.")

melawan:

s = ("this is my really, really, really, really, really, really",
    " really long string that I'd like to shorten.")

Dengan pengetikan dinamis Python, kode dapat berjalan baik, tetapi menghasilkan hasil yang salah dengan yang tidak Anda inginkan.

retracile
sumber
2

Garis miring terbalik:

s = "this is my really, really, really, really, really, really" +  \
    "really long string that I'd like to shorten."

atau bungkus dengan parens:

s = ("this is my really, really, really, really, really, really" + 
    "really long string that I'd like to shorten.")
rekursif
sumber
2
Perhatikan bahwa nilai plus diperlukan. Python menyatukan string literal yang saling mengikuti.
bukzor
2

Ini semua adalah jawaban yang bagus, tetapi saya tidak dapat menemukan plugin editor yang akan membantu saya mengedit string "secara implisit digabung", jadi saya menulis sebuah paket untuk membuatnya lebih mudah bagi saya.

Di pip (instal paragraf) jika ada yang berkeliaran di thread lama ini ingin memeriksanya. Memformat string multi-baris seperti yang dilakukan html (kompres spasi putih, dua baris baru untuk paragraf baru, jangan khawatir tentang spasi di antara baris).

from paragraphs import par


class SuddenDeathError(Exception):
    def __init__(self, cause: str) -> None:
        self.cause = cause

    def __str__(self):
        return par(
            f""" Y - e - e - e - es, Lord love you! Why should she die of
            {self.cause}? She come through diphtheria right enough the year
            before. I saw her with my own eyes. Fairly blue with it, she
            was. They all thought she was dead; but my father he kept ladling
            gin down her throat till she came to so sudden that she bit the bowl
            off the spoon. 

            What call would a woman with that strength in her have to die of
            {self.cause}? What become of her new straw hat that should have
            come to me? Somebody pinched it; and what I say is, them as pinched
            it done her in."""
        )


raise SuddenDeathError("influenza")

menjadi ...

__main__.SuddenDeathError: Y - e - e - e - es, Lord love you! Why should she die of influenza? She come through diphtheria right enough the year before. I saw her with my own eyes. Fairly blue with it, she was. They all thought she was dead; but my father he kept ladling gin down her throat till she came to so sudden that she bit the bowl off the spoon.

What call would a woman with that strength in her have to die of influenza? What become of her new straw hat that should have come to me? Somebody pinched it; and what I say is, them as pinched it done her in.

Semuanya berbaris dengan mudah dengan (Vim) 'gq'

Shay
sumber
0

Dengan \Anda dapat memperluas pernyataan ke beberapa baris:

s = "this is my really, really, really, really, really, really" + \
"really long string that I'd like to shorten."

harus bekerja.

Ikke
sumber
0

Saya cenderung menggunakan beberapa metode yang tidak disebutkan di sini untuk menentukan string besar, tetapi ini untuk skenario yang sangat spesifik. YMMV ...

  • Gumpalan teks multi-baris, seringkali dengan token yang diformat (tidak sesuai dengan yang Anda tanyakan, tetapi masih bermanfaat):

    error_message = '''
    I generally like to see how my helpful, sometimes multi-line error
    messages will look against the left border.
    '''.strip()
  • Tumbuhkan variabel sepotong demi sepotong melalui metode interpolasi string apa pun yang Anda sukai:

    var = 'This is the start of a very,'
    var = f'{var} very long string which could'
    var = f'{var} contain a ridiculous number'
    var = f'{var} of words.'
  • Baca dari file. PEP-8 tidak membatasi panjang string dalam file; hanya baris kode Anda. :)

  • Gunakan brute-force atau editor Anda untuk membagi string menjadi garis managaeble menggunakan baris baru, dan kemudian hapus semua baris baru. (Mirip dengan teknik pertama yang saya daftarkan):

    foo = '''
    agreatbigstringthatyoudonotwanttohaveanyne
    wlinesinbutforsomereasonyouneedtospecifyit
    verbatimintheactualcodejustlikethis
    '''.replace('\n', '')
Larold
sumber
0

Pilihan yang tersedia:

  • backslash :"foo" \ "bar"
  • tanda plus diikuti oleh garis miring terbalik :"foo" + \ "bar"
  • kurung :
    • ("foo" "bar")
    • kurung dengan tanda plus :("foo" + "bar")
    • PEP8, E502: garis miring terbalik berlebihan di antara tanda kurung

Menghindari

Hindari tanda kurung dengan koma: ("foo", "bar")yang mendefinisikan tupel.


>>> s = "a" \
... "b"
>>> s
'ab'
>>> type(s)
<class 'str'>
>>> s = "a" + \
... "b"
>>> s
'ab'
>>> type(s)
<class 'str'>
>>> s = ("a"
... "b")
>>> type(s)
<class 'str'>
>>> print(s)
ab
>>> s = ("a",
... "b")
>>> type(s)
<class 'tuple'>
>>> s = ("a" + 
... "b")
>>> type(s)
<class 'str'>
>>> print(s)
ab
>>> 
marcanuy
sumber
0

Jika Anda harus memasukkan string string yang lama dan ingin flake8 tutup mulut, Anda dapat menggunakannya sebagai arahan tutup mulut . Misalnya, dalam rutinitas pengujian saya menetapkan beberapa input CSV palsu. Saya menemukan bahwa membaginya di lebih banyak baris yang memiliki baris akan sangat membingungkan, jadi saya memutuskan untuk menambahkan # noqa: E501sebagai berikut:

csv_test_content = """"STATION","DATE","SOURCE","LATITUDE","LONGITUDE","ELEVATION","NAME","REPORT_TYPE","CALL_SIGN","QUALITY_CONTROL","WND","CIG","VIS","TMP","DEW","SLP","AA1","AA2","AY1","AY2","GF1","MW1","REM"
"94733099999","2019-01-03T22:00:00","4","-32.5833333","151.1666666","45.0","SINGLETON STP, AS","FM-12","99999","V020","050,1,N,0010,1","22000,1,9,N","025000,1,9,9","+0260,1","+0210,1","99999,9","24,0000,9,1",,"0,1,02,1","0,1,02,1","01,99,1,99,9,99,9,99999,9,99,9,99,9","01,1","SYN05294733 11/75 10502 10260 20210 60004 70100 333 70000="
"94733099999","2019-01-04T04:00:00","4","-32.5833333","151.1666666","45.0","SINGLETON STP, AS","FM-12","99999","V020","090,1,N,0021,1","22000,1,9,N","025000,1,9,9","+0378,1","+0172,1","99999,9","06,0000,9,1",,"0,1,02,1","0,1,02,1","03,99,1,99,9,99,9,99999,9,99,9,99,9","03,1","SYN04294733 11/75 30904 10378 20172 60001 70300="
"94733099999","2019-01-04T22:00:00","4","-32.5833333","151.1666666","45.0","SINGLETON STP, AS","FM-12","99999","V020","290,1,N,0057,1","99999,9,9,N","020000,1,9,9","+0339,1","+0201,1","99999,9","24,0000,9,1",,"0,1,02,1","0,1,02,1",,"02,1","SYN05294733 11970 02911 10339 20201 60004 70200 333 70000="
"94733099999","2019-01-05T22:00:00","4","-32.5833333","151.1666666","45.0","SINGLETON STP, AS","FM-12","99999","V020","200,1,N,0026,1","99999,9,9,N","000100,1,9,9","+0209,1","+0193,1","99999,9","24,0004,3,1",,"1,1,02,1","1,1,02,1","08,99,1,99,9,99,9,99999,9,99,9,99,9","51,1","SYN05294733 11/01 82005 10209 20193 69944 75111 333 70004="
"94733099999","2019-01-08T04:00:00","4","-32.5833333","151.1666666","45.0","SINGLETON STP, AS","FM-12","99999","V020","070,1,N,0026,1","22000,1,9,N","025000,1,9,9","+0344,1","+0213,1","99999,9","06,0000,9,1",,"2,1,02,1","2,1,02,1","04,99,1,99,9,99,9,99999,9,99,9,99,9","02,1","SYN04294733 11/75 40705 10344 20213 60001 70222="
"""  # noqa: E501
gerrit
sumber
-1

Saya telah menggunakan textwrap.dedent di masa lalu. Agak rumit jadi saya lebih suka kelanjutan baris sekarang, tetapi jika Anda benar-benar menginginkan indentasi blok, saya pikir ini hebat.

Kode Contoh (di mana trim untuk menyingkirkan '\ n' pertama dengan sebuah irisan):

import textwrap as tw
x = """\
       This is a yet another test.
       This is only a test"""
print(tw.dedent(x))

Penjelasan:

dedent menghitung lekukan berdasarkan ruang putih di baris teks pertama sebelum baris baru. Jika Anda ingin men-tweak, Anda dapat dengan mudah mengimplementasikannya menggunakanre modul.

Metode ini memiliki batasan dalam garis yang sangat panjang mungkin masih lebih lama dari yang Anda inginkan dalam hal ini metode lain yang merangkai string lebih cocok.

Tuan
sumber
1
Daripada memotong dengan x[1:]Anda dapat menggunakan backslash setelah x = """untuk menghindari baris baru pertama.
Michael Dunn