我如何在Python中包装长行而不牺牲缩进?

例如:

def fun():
    print '{0} Here is a really long sentence with {1}'.format(3, 5)

假设这超过了79个字符的推荐限制。我阅读它的方式,这里是如何缩进它:

def fun():
    print '{0} Here is a really long \
sentence with {1}'.format(3, 5)

但是,使用这种方法,连续行的缩进与fun()的缩进匹配。这看起来有点丑。如果有人要检查我的代码,由于这个print语句,不均匀的缩进看起来会很糟糕。

如何在不牺牲代码可读性的情况下有效地缩进行呢?


当前回答

使用相邻字符串字面量的连接,以及格式化字符串字面量是要走的方式:

x = 2
sep = 2 * '\n'
print(
    'This message is so long that it requires '
    f'more than {x} lines.{sep}'
    'And more lines may be needed.')

这种方法符合PEP 8并允许更好地使用空间。

不需要+操作符,连续行不需要反斜杠,不需要不规则的缩进,不需要容易出错的+=到累加器字符串变量(可能会被错误输入为=,导致无声错误),打印下面没有杂乱的括号(参数被放置在它们自己的缩进级别中,打印缩进级别的下一个元素是下一个语句)。

在包含打印的行下面的行上开始字符串(减少缩进,并且更易于阅读)。可读性既来自于打印(突出,通过在自己的行上,也来自于这种形式的连续语句的统一对齐。

在引发异常时,这种方法减少缩进的效果更加明显:

raise ModuleNotFoundError(
    'aaaaaaaaaaaaaaaaaaaaaaaa'
    'aaaaaaaaaaaaaaaaaaaaaaaa'
    f'aaaaa {x} aaaaa')

对于格式化字符串字面量(由前缀“f”表示,如在f'…'中),原始字符串可以通过组合前缀“r”和“f”来格式化字符串字面量:

rf'This is a formatted raw string, {sep}here is a backslash \.'

注意,原始字符串是包含反斜杠而不写入\\的必要条件。否则,在未来的CPython版本中,将引发SyntaxError。从Python 3.9开始,会引发DeprecationWarning:

python -X dev -c '"\q"'

输出:

<string>:1: DeprecationWarning: invalid escape sequence \q

替换的内容非常易读。特别是,这种方法使得编写生成代码或数学公式的代码成为一项非常愉快的任务。

很少情况下,str.format方法可能是合适的,这取决于所需要的替换。它可以这样使用:

print((
    'This message is so long that it requires '
    'more than {x} lines.{sep}'
    'And more lines may be needed.'
    ).format(x=x, sep=sep))

其他回答

def fun():
    print(('{0} Here is a really long '
           'sentence with {1}').format(3, 5))

相邻的字符串文字在编译时连接,就像在c中一样。http://docs.python.org/reference/lexical_analysis.html#string-literal-concatenation是了解更多信息的好地方。

你可以使用下面的代码,其中缩进不重要:

>>> def fun():
        return ('{0} Here is a really long'
        ' sentence with {1}').format(3, 5)

你只需要把字符串括在括号里。

你可以使用Python连接彼此相邻的字符串字面值的事实:

>>> def fun():
...     print '{0} Here is a really long ' \
...           'sentence with {1}'.format(3, 5)

使用相邻字符串字面量的连接,以及格式化字符串字面量是要走的方式:

x = 2
sep = 2 * '\n'
print(
    'This message is so long that it requires '
    f'more than {x} lines.{sep}'
    'And more lines may be needed.')

这种方法符合PEP 8并允许更好地使用空间。

不需要+操作符,连续行不需要反斜杠,不需要不规则的缩进,不需要容易出错的+=到累加器字符串变量(可能会被错误输入为=,导致无声错误),打印下面没有杂乱的括号(参数被放置在它们自己的缩进级别中,打印缩进级别的下一个元素是下一个语句)。

在包含打印的行下面的行上开始字符串(减少缩进,并且更易于阅读)。可读性既来自于打印(突出,通过在自己的行上,也来自于这种形式的连续语句的统一对齐。

在引发异常时,这种方法减少缩进的效果更加明显:

raise ModuleNotFoundError(
    'aaaaaaaaaaaaaaaaaaaaaaaa'
    'aaaaaaaaaaaaaaaaaaaaaaaa'
    f'aaaaa {x} aaaaa')

对于格式化字符串字面量(由前缀“f”表示,如在f'…'中),原始字符串可以通过组合前缀“r”和“f”来格式化字符串字面量:

rf'This is a formatted raw string, {sep}here is a backslash \.'

注意,原始字符串是包含反斜杠而不写入\\的必要条件。否则,在未来的CPython版本中,将引发SyntaxError。从Python 3.9开始,会引发DeprecationWarning:

python -X dev -c '"\q"'

输出:

<string>:1: DeprecationWarning: invalid escape sequence \q

替换的内容非常易读。特别是,这种方法使得编写生成代码或数学公式的代码成为一项非常愉快的任务。

很少情况下,str.format方法可能是合适的,这取决于所需要的替换。它可以这样使用:

print((
    'This message is so long that it requires '
    'more than {x} lines.{sep}'
    'And more lines may be needed.'
    ).format(x=x, sep=sep))

我很惊讶上面没有人提到隐式风格。我的偏好是使用paren来包装字符串,同时在视觉上对齐字符串行。就我个人而言,我认为这看起来比在一个带标签的新行上开始字符串的开头更干净,更紧凑。

注意,这些paren不是方法调用的一部分——它们只是隐式的字符串字面值连接。

Python 2:

def fun():
    print ('{0} Here is a really '
           'long sentence with {1}').format(3, 5)

Python 3(带有打印函数的parens):

def fun():
    print(('{0} Here is a really '
           'long sentence with {1}').format(3, 5))

就我个人而言,我认为将连接长字符串文字与打印它分开是最干净的:

def fun():
    s = ('{0} Here is a really '
         'long sentence with {1}').format(3, 5)
    print(s)