Cách viết chuỗi rất dài phù hợp với PEP8 và ngăn E501


203

Vì PEP8 đề nghị giữ dưới quy tắc cột 80 cho chương trình python của bạn, làm thế nào tôi có thể tuân thủ quy tắc đó với các chuỗi dài, nghĩa là

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

Làm thế nào tôi có thể mở rộng dòng này sang dòng sau, tức là

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

Câu trả lời:


116

Kết nối ngầm có thể là giải pháp sạch nhất:

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

Chỉnh sửa theo phản ánh Tôi đồng ý rằng đề xuất của Todd sử dụng dấu ngoặc thay vì tiếp tục dòng là tốt hơn cho tất cả các lý do anh ta đưa ra. Do dự duy nhất tôi có là nó tương đối dễ nhầm lẫn giữa các chuỗi ngoặc đơn với các bộ dữ liệu.


4
Đây là lý do tại sao tôi cảm thấy như một thằng ngốc đăng câu hỏi. Chúc mừng.
Federer

8
Đây là sự tiếp tục dòng bằng cách thoát khỏi dòng cuối, không chỉ đơn thuần là kết nối ngầm và cho đến khi gần đây bị cấm rõ ràng trong PEP8, mặc dù bây giờ có trợ cấp, nhưng KHÔNG cho các chuỗi dài. Câu trả lời của Todd dưới đây là chính xác.
Aaron Hall

4
Tôi thích PEP8, nhưng đây là một phần của PEP8 mà tôi không thích. Tôi cảm thấy như sự tiếp tục ngầm là rõ ràng hơn, vì khả năng nhầm lẫn với các bộ dữ liệu
monknomo

1
Hãy nhớ không thêm bất kỳ khoảng trống nào sau \
Mrinal Saurabh

Nếu dòng dài nằm ở giữa một chuỗi nhiều dòng dài thì sao?
Thayne

299

Ngoài ra, vì các hằng chuỗi lân cận được tự động nối, bạn cũng có thể mã nó như thế này:

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

Lưu ý không có dấu cộng và tôi đã thêm dấu phẩy và khoảng trắng theo định dạng của ví dụ của bạn.

Cá nhân tôi không thích dấu gạch chéo ngược và tôi nhớ rằng đã đọc ở đâu đó rằng việc sử dụng nó thực sự không được ủng hộ cho hình thức này rõ ràng hơn. Hãy nhớ "Rõ ràng là tốt hơn so với ngầm."

Tôi coi dấu gạch chéo ngược là ít rõ ràng và ít hữu ích hơn vì điều này thực sự thoát khỏi ký tự dòng mới. Không thể đặt một bình luận cuối dòng sau nó nếu cần thiết. Có thể làm điều này với các hằng chuỗi được nối:

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

Tôi đã sử dụng một tìm kiếm Google về "độ dài dòng python" trả về liên kết PEP8 làm kết quả đầu tiên, nhưng cũng liên kết đến một bài đăng StackOverflow tốt khác về chủ đề này: " Tại sao Python PEP-8 chỉ định độ dài dòng tối đa 79 ký tự? "

Một cụm từ tìm kiếm tốt khác sẽ là "tiếp tục dòng python".


8
+1: "Cá nhân tôi không thích dấu gạch chéo ngược và tôi nhớ rằng đã đọc ở đâu đó rằng việc sử dụng nó thực sự không được ủng hộ cho hình thức này rõ ràng hơn. Hãy nhớ" Rõ ràng là tốt hơn ngầm định. ""
Alberto Megía

13
Đối với tất cả những người nhận được một tuple và tự hỏi tại sao. Không thêm dấu phẩy vào cuối dòng ở đây, điều đó sẽ dẫn đến một tuple, không phải là một chuỗi. ;)
bugmenot123

7
Không thêm ký tự + rõ ràng hơn ví dụ đã cho? Tôi vẫn sẽ xem xét điều này ngầm. tức là "str1" + "str2"thay vì"str1" "str2"
user1318135

4
Tôi thực sự đồng ý rằng dấu cộng rõ ràng hơn, nhưng nó làm một điều khác. Nó biến chuỗi thành một biểu thức được ước tính, thay vì chỉ định một chuỗi duy nhất trong một số phần. Tôi không chắc chắn nhưng tôi nghĩ rằng điều này được thực hiện trong quá trình phân tích cú pháp trong khi biểu thức cần được thực hiện sau đó. Sự khác biệt tốc độ có lẽ là không đáng kể trừ khi có một số lượng lớn trong số họ. Nhưng về mặt thẩm mỹ, tôi thích cách ghép tự động hơn vì nó là một ký tự ít lộn xộn hơn trên mỗi dòng.
Todd

4
Cú pháp này cũng giữ khả năng áp dụng định dạng chuỗi như:('this is my really, really, really, really, really long {} ' 'that I'd really, really, really, like to {}').format(var1, var2))
Tim

16

Tôi nghĩ rằng từ quan trọng nhất trong câu hỏi của bạn là "gợi ý".

Tiêu chuẩn mã hóa là những điều buồn cười. Thông thường hướng dẫn mà họ cung cấp có cơ sở thực sự tốt khi được viết (ví dụ: hầu hết các thiết bị đầu cuối không thể hiển thị> 80 ký tự trên một dòng), nhưng theo thời gian chúng trở nên lỗi thời về mặt chức năng, nhưng vẫn tuân thủ chặt chẽ. Tôi đoán những gì bạn cần làm ở đây là cân nhắc những ưu điểm tương đối của việc "phá vỡ" đề xuất cụ thể đó chống lại khả năng đọc và tính chính xác của mã của bạn.

Xin lỗi điều này không trực tiếp trả lời câu hỏi của bạn.


Tôi hoàn toàn đồng ý. Có một quy tắc kiểu Java tương tự cũng trở nên lỗi thời (IMHO).
Iker Jimenez

Vâng, tôi đồng ý, tuy nhiên, tôi đã suy nghĩ về việc tôi sẽ tuân theo nó như thế nào trong ví dụ cụ thể này. Tôi luôn cố gắng giữ các lớp, phương thức thành <80 ký tự, tuy nhiên tôi muốn nói một chuỗi như thế này không có tác dụng gì ngoài có lẽ là một chuỗi âm.
Federer

1
Bạn cũng cần cân nhắc sở thích cá nhân của mình với tiêu chuẩn mã hóa toàn cộng đồng. Bạn muốn những người mới có thể vào và thoải mái với định dạng mã từ ngày đầu tiên.
retracile

1
Tôi tự biết, tôi có xu hướng tuân theo giới hạn 80 ký tự chỉ vì tôi vẫn thực hiện hầu hết mã hóa trong IDLE và tôi không thích cách nó xử lý cuộn ngang. (Không có thanh cuộn)
Tofystedeth

@retracile - vâng, bạn làm. Tôi không nói "Bạn phải bỏ qua hướng dẫn", thay vào đó gợi ý rằng trong một số trường hợp, hướng dẫn không nhất thiết phải có vì lợi ích của cộng đồng. Tôi đã không nhận thức được các hạn chế của IDLE (như được đăng bởi Tofystedeth) nhưng trong trường hợp đó, có một lập luận nổi bật để tuân theo quy ước.
ZombieSheep

13

Bạn đã mất một khoảng trắng, và có lẽ bạn cần một ký tự tiếp tục dòng, tức là. a \.

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

hoặc thậm chí:

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

Parens cũng sẽ hoạt động thay vì tiếp tục dòng, nhưng bạn có nguy cơ ai đó nghĩ rằng bạn dự định có một tuple và đã quên một dấu phẩy. Lấy ví dụ:

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

đấu với:

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

Với kiểu gõ động của Python, mã có thể chạy theo bất kỳ cách nào, nhưng tạo ra kết quả không chính xác với cách bạn không có ý định.


2

Dấu gạch chéo ngược:

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

hoặc bọc trong parens:

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

2
Lưu ý rằng điểm cộng là cần thiết. Python nối các chuỗi ký tự theo nhau.
bukzor

2

Đây đều là những câu trả lời tuyệt vời, nhưng tôi không thể tìm thấy một plugin biên tập nào có thể giúp tôi chỉnh sửa các chuỗi "được kết nối ngầm", vì vậy tôi đã viết một gói để giúp tôi dễ dàng hơn.

Trên pip (cài đặt đoạn văn) nếu bất cứ ai lang thang chủ đề cũ này muốn kiểm tra nó. Định dạng chuỗi nhiều dòng theo cách html thực hiện (nén khoảng trắng, hai dòng mới cho một đoạn mới, không phải lo lắng về khoảng trắng giữa các dòng).

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")

trở thành ...

__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.

Mọi thứ dễ dàng xếp hàng với (Vim) 'gq'


0

Với một \bạn có thể mở rộng các câu lệnh thành nhiều dòng:

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

nên làm việc.


0

Tôi có xu hướng sử dụng một vài phương thức không được đề cập ở đây để chỉ định các chuỗi lớn, nhưng chúng dành cho các kịch bản rất cụ thể. YMMV ...

  • Các đốm văn bản nhiều dòng, thường có mã thông báo được định dạng (không hoàn toàn như những gì bạn đang hỏi, nhưng vẫn hữu ích):

    error_message = '''
    I generally like to see how my helpful, sometimes multi-line error
    messages will look against the left border.
    '''.strip()
  • Phát triển từng mảnh biến thông qua bất kỳ phương pháp nội suy chuỗi nào bạn thích:

    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.'
  • Đọc nó từ một tập tin. PEP-8 không giới hạn độ dài của chuỗi trong một tệp; chỉ các dòng mã của bạn. :)

  • Sử dụng brute-force hoặc trình soạn thảo của bạn để phân tách chuỗi thành các dòng Manageaeble bằng cách sử dụng dòng mới và sau đó xóa tất cả dòng mới. (Tương tự như kỹ thuật đầu tiên tôi liệt kê):

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

0

Tùy chọn có sẵn:

  • dấu gạch chéo ngược :"foo" \ "bar"
  • dấu cộng theo sau dấu gạch chéo ngược :"foo" + \ "bar"
  • ngoặc :
    • ("foo" "bar")
    • dấu ngoặcdấu cộng :("foo" + "bar")
    • PEP8, E502: dấu gạch chéo ngược là dự phòng giữa các dấu ngoặc

Tránh

Tránh dấu ngoặc bằng dấu phẩy: ("foo", "bar")định nghĩa một tuple.


>>> 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
>>> 

0

Nếu bạn phải chèn một chuỗi ký tự dài và muốn flake8 im lặng, bạn có thể sử dụng nó để tắt các lệnh . Ví dụ: trong quy trình kiểm tra tôi đã xác định một số đầu vào CSV giả. Tôi thấy rằng việc chia nó thành nhiều dòng hơn mà nó có các hàng sẽ rất khó hiểu, vì vậy tôi quyết định thêm một dòng # noqa: E501như sau:

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

-1

Tôi đã sử dụng textwrap.dedent trong quá khứ. Bây giờ nó hơi cồng kềnh nên tôi thích tiếp tục dòng hơn nhưng nếu bạn thực sự muốn khối thụt lề, tôi nghĩ điều này thật tuyệt.

Mã ví dụ (trong đó phần cắt là để loại bỏ '\ n' đầu tiên bằng một lát):

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

Giải trình:

cống hiến tính toán thụt lề dựa trên khoảng trắng trong dòng văn bản đầu tiên trước một dòng mới. Nếu bạn muốn điều chỉnh nó, bạn có thể dễ dàng thực hiện lại bằng cách sử dụngre mô-đun.

Phương pháp này có những hạn chế trong đó các dòng rất dài vẫn có thể dài hơn bạn muốn trong trường hợp các phương thức khác nối chuỗi phù hợp hơn.


1
Thay vì cắt tỉa với x[1:]bạn, bạn có thể đặt dấu gạch chéo ngược sau x = """để tránh dòng mới đầu tiên.
Michael Dunn
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.