如何编写符合PEP8的很长的字符串并防止E501


203

正如PEP8建议将python程序的规则保持在80列以下,我该如何使用长字符串来遵守该规则,即

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

我如何将其扩展到以下行,即

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

Answers:


116

隐式串联可能是最干净的解决方案:

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

编辑在反思我同意,托德的建议,请使用括号,而不是续行是所有他给出的理由更好。我唯一的犹豫是将带括号的字符串与元组混淆是相对容易的。


4
这就是为什么我觉得自己像个白痴在发这个问题。干杯。
费德勒2009年

8
这是通过保留转义符而不是隐式连接来延续行,直到最近在PEP8中明确禁止,尽管现在有允许,但长字符串则不行。托德下面的答案是正确的。
亚伦·霍尔

4
我喜欢PEP8,但这是我不喜欢的PEP8的一部分。我觉得隐含的延续更加清晰,因为可能会与元组混淆
monknomo

1
切记不要\后添加任何空格
Mrinal SAURABH

如果长线在多行长字符串的中间怎么办?
Thayne

298

另外,由于相邻的字符串常量是自动连接的,因此您也可以这样编码:

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

请注意没有加号,我在示例格式之后添加了额外的逗号和空格。

我个人不喜欢反斜杠,并且我记得在某处读到它的使用实际上已被弃用,而倾向于这种更明确的形式。记住“显式胜于隐式”。

我认为反斜杠不太清楚,用处也不大,因为这实际上是在换行符的转义。如果有必要在行末尾添加注释。可以使用串联的字符串常量来做到这一点:

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

我使用Google搜索“ python行长”来返回PEP8链接作为第一个结果,同时还链接到另一个有关该主题的StackOverflow帖子:“ 为什么Python PEP-8应该指定最大行长为79个字符?

另一个很好的搜索词组是“ python行连续”。


8
+1:“我个人不喜欢反斜杠,我记得在某处曾有人不赞成使用该斜杠,而赞成使用这种更明确的形式。请记住,“显式优于隐式。”
阿尔贝托·梅加

13
对于每个获得元组并想知道为什么的人。不要在此处在行末添加逗号,这将导致元组而不是字符串。;)
bugmenot123 2015年

7
添加+字符是否比给定示例更明确?我仍然认为这是隐性的。即"str1" + "str2"而不是"str1" "str2"
user1318135 '17

4
我实际上同意加号更为明确,但是它做的却不同。它将字符串转换为要计算的表达式,而不是指定多个字符串常量。我不确定,但是我认为这是在解析过程中完成的,而表达式需要稍后执行。除非有大量的速度差异,否则速度差异可以忽略不计。但从美学上来说,我更喜欢自动串联,因为它是每行少一个混乱的字符。
托德

4
这种语法还保留了应用字符串格式的可能性,例如:('this is my really, really, really, really, really long {} ' 'that I'd really, really, really, like to {}').format(var1, var2))
Tim

16

我认为您的问题中最重要的词是“建议”。

编码标准很有趣。通常,他们提供的指南在编写时有很好的基础(例如,大多数终端无法在一行上显示> 80个字符),但是随着时间的推移,它们在功能上已过时,但仍然严格遵守。我想您在这里需要做的是权衡“打破”该特定建议与代码的可读性和可维护性的相对优点。

抱歉,这不能直接回答您的问题。


我完全同意。有一个类似的Java样式规则也已过时(IMHO)。
Iker Jimenez 2009年

是的,我同意,但是在这个特定示例中,如何遵循它一直是我的难题。我总是尝试将类和方法的字符数保持在80个以内,但是我想说这样的字符串除了可能是负数之外没有任何作用。
费德勒2009年

1
您还需要根据社区范围的编码标准权衡您的个人偏好。您希望新人们能够从第一天开始就对代码格式感到满意。
09年

1
我自己就知道,我倾向于坚持80个字符的限制,只是因为我仍然在IDLE中进行大部分编码,而且我不喜欢它处理水平滚动的方式。(无滚动条)
Tofystedeth's

@retracile-是的,您知道。我并不是说“您必须忽略指导”,而是建议在某些情况下不一定为了社区的利益而存在指导。我不了解IDLE的限制(由Tofystedeth发布),但是在这种情况下,有一个强烈的理由要遵循公约。
ZombieSheep 2009年

13

您丢失了一个空格,并且可能需要换行符,即。一个\

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

甚至:

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

Parens也可以代替行继续,但是您可能会冒险有人认为您打算创建一个元组而忘记了逗号。举个例子:

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

与:

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

使用Python的动态类型,代码可能会以任何一种方式运行,但是会产生与您不想要的结果相同的错误结果。


2

反斜杠:

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

或包裹在括号中:

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

2
请注意,加号是必需的。Python将字符串文字串联在一起。
bukzor 2011年

2

这些都是很好的答案,但是我找不到能帮助我编辑“隐式连接”字符串的编辑器插件,因此我编写了一个程序包使它更容易使用。

在pip(安装段落)上,如果有人在徘徊这个旧线程想要将其签出。格式化html格式的多行字符串(压缩空格,为新段落添加两个换行符,不必担心行之间的空格)。

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

变成...

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

一切都轻松地与(Vim)'gq'对齐


0

使用a \可以将语句扩展到多行:

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

应该管用。


0

我倾向于使用一些此处未提及的方法来指定大字符串,但这是针对非常特定的场景的。YMMV ...

  • 多行文本,通常带有格式化标记(不是您所要的,但仍然有用):

    error_message = '''
    I generally like to see how my helpful, sometimes multi-line error
    messages will look against the left border.
    '''.strip()
  • 通过您喜欢的任何字符串插值方法逐段增加变量:

    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.'
  • 从文件中读取。PEP-8不会限制文件中字符串的长度;只是您的代码行。:)

  • 使用蛮力或您的编辑器使用换行符将字符串拆分为可换行,然后删除所有换行符。(类似于我列出的第一种技术):

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

0

可用选项:

  • 反斜杠"foo" \ "bar"
  • 加号后跟反斜杠"foo" + \ "bar"
  • 括号
    • ("foo" "bar")
    • 加号的括号("foo" + "bar")
    • PEP8,E502:括号之间的反斜杠是多余的

避免

避免用逗号括起来:("foo", "bar")定义一个元组。


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

如果您必须插入一个长字符串文字并希望flake8关闭,则可以使用它的关闭指令。例如,在测试例程中,我定义了一些伪造的CSV输入。我发现将其分割成行的更多行会造成极大的混乱,因此我决定添加# noqa: E501以下内容:

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

我过去使用过textwrap.dedent。这有点麻烦,所以我现在更喜欢连续行,但是如果您真的想要块缩进,我认为这很棒。

示例代码(其中修剪将去除带有切片的第一个“ \ n”):

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

说明:

dedent根据换行之前第一行文本中的空格来计算缩进。如果您想对其进行调整,则可以使用该re模块轻松地重新实现它。

此方法有局限性,因为很长的行可能仍然比您想要的更长,在这种情况下,其他将字符串连接起来的方法更合适。


1
x[1:]可以使用反斜杠代替x = """第一行,而不用修剪。
迈克尔·邓恩
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.