Python中在链式调用方法时正确的换行风格

78

我有一些类似这样的代码。断点应该在句号之前还是之后?

# before
my_var = somethinglikethis.where(we=do_things).where(we=domore).where(we=everdomore)

# this way
my_var = somethinglikethis.where(we=do_things) \
                          .where(we=domore) \
                          .where(we=everdomore)

# or this way
my_var = somethinglikethis.where(we=do_things). \
                           where(we=domore). \
                           where(we=everdomore)
3个回答

129

PEP 8建议使用括号,这样就不需要\,并且温和地建议在二元运算符之前而不是之后进行断行。因此,格式化代码的首选方式如下:

my_var = (somethinglikethis
          .where(we=do_things)
          .where(we=domore)
          .where(we=everdomore))

两个相关的段落是来自于最大行长度部分的以下内容:

首选的换行方式是使用Python中括号、方括号和花括号内隐含的行连接。可以通过将表达式包装在括号中来将长行分成多行。这应该优先于使用反斜杠进行行连接。

... 和整个二进制运算符前后是否应该换行?部分:

Should a line break before or after a binary operator?

For decades the recommended style was to break after binary operators. But this can hurt readability in two ways: the operators tend to get scattered across different columns on the screen, and each operator is moved away from its operand and onto the previous line. Here, the eye has to do extra work to tell which items are added and which are subtracted:

# No: operators sit far away from their operands
income = (gross_wages +
          taxable_interest +
          (dividends - qualified_dividends) -
          ira_deduction -
          student_loan_interest)

To solve this readability problem, mathematicians and their publishers follow the opposite convention. Donald Knuth explains the traditional rule in his Computers and Typesetting series: "Although formulas within a paragraph always break after binary operations and relations, displayed formulas always break before binary operations"

Following the tradition from mathematics usually results in more readable code:

# Yes: easy to match operators with operands
income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

In Python code, it is permissible to break before or after a binary operator, as long as the convention is consistent locally. For new code Knuth's style is suggested.

请注意,如上所述,PEP 8曾经在断开运算符周围的位置方面给出相反的建议,并为了记录而引用了以下内容:

The preferred way of wrapping long lines is by using Python's implied line continuation inside parentheses, brackets and braces. Long lines can be broken over multiple lines by wrapping expressions in parentheses. These should be used in preference to using a backslash for line continuation. Make sure to indent the continued line appropriately. The preferred place to break around a binary operator is after the operator, not before it. Some examples:

class Rectangle(Blob):

    def __init__(self, width, height,
                 color='black', emphasis=None, highlight=0):
        if (width == 0 and height == 0 and
            color == 'red' and emphasis == 'strong' or
            highlight > 100):
            raise ValueError("sorry, you lose")
        if width == 0 and height == 0 and (color == 'red' or
                                           emphasis is None):
            raise ValueError("I don't think so -- values are %s, %s" %
                             (width, height))
        Blob.__init__(self, width, height,
                      color, emphasis, highlight)

11
对于像“+”和“or”这样通常周围有空格的运算符,推荐使用“操作符后断行”的方式是有道理的。但对于“.”运算符,很可能应该使用“操作符前断行”的方式。否则,我们在英语中的经验告诉我们,会将尾随的点视为句号而不是方法/属性查找。 - Raymond Hettinger
1
请注意,PEP8的Rectangle示例在2013年进行了更新,使用新的多行if缩进方式。(我曾尝试编辑答案,但并未成功。看这里。) - duozmo

3

就此而言,autopep8(带有 --aggressive 标志)从您的原始代码生成了以下内容:

my_var = somethinglikethis.where(
    we=do_things).where(
    we=domore).where(
    we=everdomore)

但是我同意--Bastien的解决方案更加优雅。


2

做有效的事情。

此外,可以查看关于Python中缩进误解的白皮书。该文档可以在此处找到:这里

它开始时说:

"在Python源代码中,空格是有意义的。"

不是完全如此。只有你语句左侧的缩进级别是有意义的(即语句最左侧的空格)。其他地方的空格都没有意义,可以像其他任何语言一样使用。您还可以在任何位置插入什么都不包含的空行(或只包含任意空格)。

希望对您有所帮助。


2
-1;“您还可以在任何地方插入不包含任何内容(或仅包含任意空格)的空行。”是明显不正确的。如果在print和开括号之间放置换行符,则print('Hello, World')将无法正常工作。我想不出有关“空格不重要,可以随意使用”的任何语言都是正确的陈述;在函数中使用return1通常会导致语法错误,而return 1则是合法的。 - Mark Amery

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