如何让我的Python代码每行不超过80个字符?

60
我写了一些Python代码,其中有一些行超过了80个字符的长度,而我需要保持在这个阈值以下。我该如何修改我的代码来缩短行的长度?

47
将代码保持在80列以下是应该在十年前就消失的东西。针对80x25终端是荒谬的,会导致丑陋的代码。 - Glenn Maynard
57
我强烈不同意Glenn Maynard的看法。大多数人仍然使用80个字符宽度的编辑器窗口,因为通常有多个窗口需要保持可见。 - Kimvais
13
你可以做自己喜欢的事情,但我绝不会破坏我的代码来支持那些坚持在微小的窗口中编辑代码的人。Devin的回答展示了当你这样做时,代码会变得多么丑陋和不自然。一个明智的限制是大约120个字符宽度。 - Glenn Maynard
14
实际上,我认为我的例子展示了当你应用14列限制时代码变得多么丑陋和不自然。如果问题是关于120字符限制的,并且使用相同的“丑陋”例子,我的答案将是一样的,所以你的论点并没有让我非常信服。就个人而言,我非常少关心这个问题。如果我设置任何最大长度,某些行不可避免地必须缩短/分割。在一定范围内,将最大值设置为较小的值是可以接受的,80/120似乎在这个范围内。而80是现状,所以我就使用它。代码质量实际上并不会受到影响。 - Devin Jeanpierre
23
那可能是我听过的最“不符合Python风格”的评论了:“我当然不会为了让别人更容易读懂我的代码而使它变得不那么美观。” - Kimvais
显示剩余8条评论
4个回答

63
我目前使用的编辑器(Kate)已经配置为在行长达到或超过80个字符时,在单词边界处引入换行符。这使得超出边界变得显而易见。此外,还有一条红线标记80个字符位置,提前警告我该行将要溢出。这些让我能够规划逻辑行以适合多个物理行。
至于如何实际适应它们,有几种机制。您可以用\结束该行,但这很容易出错。
# works
print 4 + \
    2

# doesn't work
print 4 + \ 
    2

区别在哪里? 区别是看不见的——第二种情况后面有一个空格字符。糟糕!

应该怎么做呢? 好吧,用括号括起来。

print (4 + 
    2)

不需要反斜杠。这实际上是通用的,你永远不需要使用反斜杠。即使是属性访问边界也不需要!

print (foo
    .bar())

对于字符串,您可以显式地添加它们,也可以使用 C 风格的连接隐式添加。

# all of these do exactly the same thing
print ("123"
    "456")
print ("123" + 
    "456")
print "123456"

最后,任何形式的括号((),[],{}等)都可以在任何位置换行。因此,例如,您可以使用多行列表文字,只要元素由逗号分隔即可。

Python的官方文档中可以找到更多信息。另外,一个快速提示,PEP-8指定79个字符为限制,而不是80个--如果您有80个字符,那么您已经超过了限制。


24
请尽量避免使用反斜杠(backslashes),只有当其他方法都不行时再使用(见下方回答中的链接)。 - Kimvais
区别是看不见的——第二种情况中有一个空格字符。在反斜杠之后,也就是说。只是提一下。 - Boldewyn
3
@Kimvais:这不正是Devin在这里建议的吗?他甚至展示了一个导致此建议的示例错误。 - Boldewyn
4
谁的编辑器在保存时不会删除行末空格? - Tor Valamo
6
括号并不是"通用的". 例如,它们不能在赋值语句中使用((very_long_var_name = … <newline> …)),也不能在像(with open('very long file name') <newline> as …):这样的语句中使用。实际上,它们只能用于表达式(而不是语句)中,即那些被"计算"并返回值的东西。 - Eric O. Lebigot
显示剩余3条评论

23
如果超过80个字符的代码是函数调用(或定义),则分隔参数行。Python会识别括号,并将其视为一行。
function(arg, arg, arg, arg,
         arg, arg, arg...)

如果超过80个字符的代码是一行不自然可分割的代码,你可以使用反斜杠\来“转义”换行符。

some.weird.namespace.thing.that.is.long = ','.join(strings) + \
                                          'another string'

你还可以利用括号来帮助你。

some.weird.namespace.thing.that.is.long = (','.join(strings) +
                                           'another string')

所有类型的集合括号 {}(字典/集合)、[](列表)、()(元组)都可以跨多行进行分隔,没有问题。这样可以实现更好的格式化。

mydict = {
    'key': 'value',
    'yes': 'no'
}

1
为什么不呢? thing = some.weird.namespace.thing.that, thing.long = ','.join(strings) + 'another string' - guyskk

23

我对之前的回答有两点补充:

字符串可以自动拼接,这非常方便:

this_is_a_long_string = ("lkjlkj lkj lkj mlkj mlkj mlkj mlkj mlkj mlkj "
                         "rest of the string: no string addition is necessary!"
                         " You can do it many times!")

注意这是高效的:这并不会导致代码运行时计算字符串连接操作:相反,这将被视为一个单一的长字符串文字,因此它是高效的。

Devin的答案有一个小陷阱:"括号"语法实际上并不是"通用的"。例如,d[42] = "H22G" 不能写成

(d
 [42] = "H2G2")

可以在“计算”表达式(不包括像上面那样的赋值(=))周围使用括号。

另一个例子是以下代码,它曾经会在Python 3.9之前某个时间点生成语法错误:

with (open("..... very long file name .....")
      as input_file):

实际上,括号不能放在任何语句周围,更普遍地说,只能放在表达式周围。

在这些情况下,可以使用“”语法,或者更好的方法(如果可能的话应避免“”),将代码拆分成多个语句。


1
“with (open(...”语句在我的Python 3.9中没有生成语法错误。 - Evan

19

Python惯用法指出:

最后才考虑使用反斜杠

如果有可能,尽量避免使用反斜杠。例如,如果你有一个类似于 a.train.wreck.that.spans.across.a.dozen.cars.and-multiple.lines.across.the.whole.trainyard.and.several.states() 的代码块,则可这样做:

lines = a.train.wreck.that.spans.across.a.dozen.cars.and-multiple.lines
lines.across.the.whole.trainyard.and.several.states()

或者更好的方法是重构你的代码。拜托了。


1
如果您需要打印大量静态文本,例如CLI脚本的使用说明,我想看看您如何“重构”它。 - Boldewyn
13
使用 print("""...文本...""")print("文本" "文本" "文本") - Kimvais
Python3.6的f-string print(f'{text:-^80}') 或者 print('{:-^80}'.format(text)) - guyskk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接