交互式提示中的空行规则

11 投票
4 回答
5690 浏览
提问于 2025-04-17 07:45

为什么在Python的交互式提示和从命令行运行程序时,空行的规则会不一样呢?

因为空行会被忽略,所以我喜欢多用一些空行。不过,在交互式提示中,空行是用来结束循环的。因此,当我把一段代码粘贴到交互式提示中时,由于循环中有很多空行,我总是会遇到缩进错误。这让调试和开发的过程变得有点麻烦。用#代替空行可以解决这个问题,但我还是喜欢我的空行。

更让人烦恼的是,不同的提示行为也不一样(比如Python的命令行和IPython)。在Python的交互式提示中,我会在预期的地方遇到错误,而IPython却会继续执行缩进的代码,仿佛它不是循环的一部分,也不会报错。

我觉得应该有简单的解决办法,但我还不知道。我在用vi来编辑和使用Python/IPython提示。

4 个回答

1

IPython v5 现在可以很好地处理带缩进的空白多行文本了:

http://blog.jupyter.org/2016/07/08/ipython-5-0-released/

从上面的博客文章中:

prompt_toolkit 是一个很棒的库,由 Jonathan Slenders 开发,最近达到了 1.0 版本。它比 readline 更强大,提供了许多高级功能,可以在终端中编辑文本,从而大大提升用户体验。由于它是一个跨平台的库,所有在 Linux/Unix、macOS 和 Windows 上的用户都能享受到这些改进。得益于 prompt_toolkit,IPython 现在支持:

  • 输入时的语法高亮显示
  • 真正的多行编辑(上下箭头键可以在行间移动)
  • 多行粘贴时不会破坏缩进,也不会立即执行代码
  • 更好的代码补全界面(我们计划进一步改进)
  • 可选的鼠标支持
5

...为什么在Python中,交互式提示和从命令行运行程序时对空行的规则不同呢?

因为,当你按下回车键时,解释器会立即尝试执行代码,但它需要空行来判断你的函数、循环、条件语句或其他缩进块是否结束。如果你在写一个函数时,在最后一行之前加上空行,实际上是没用的(甚至会导致错误)。在这种情况下,空行是用来表示函数结束的。

你可以从命令行运行一个没有空行的脚本,比如

for i in range(3):
    print i
a = 1000
print a

会产生

$ python test.py
0
1
2
1000

但是如果你把这个粘贴到解释器里,你会得到

>>> for i in range(3):
...     print i
... a = 1000
  File "<stdin>", line 3
a = 1000
^
SyntaxError: invalid syntax
>>> print a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined

如果你加一个空行来表示循环结束

for i in range(3):
    print i

a = 1000
print a

然后粘贴到解释器中,

>>> for i in range(3):
...     print i
...
0
1
2
>>> a = 1000
>>> print a
1000

而且这个空行必须是完全空的,连空格(可能是你的编辑器自动添加的)都会导致解释器出错。

如果你想把一个类粘贴到解释器中,那么你不希望任何行之间有空格,包括方法之间。这和PEP8规范有冲突,意味着你要么遵循PEP8,要么兼容解释器,但不能两者兼得。

因此,如果你想把代码复制粘贴到标准的Python解释器中,你需要遵循一些稍微不同的规则。

  • 顶层函数和类定义之间要用两行空行隔开。
  • 顶层模块代码(不在函数或类内)结束一个缩进块,比如for循环、try/except或if语句时,需要一个空行。
  • 在函数、类或方法内部不能使用空行(除了\或#)。

遵循这些规则,你就能在解释器中粘贴代码。不过,对于类来说,你在方法前后需要一个空行,这样就不完全符合PEP8规范了。

3

PEP 8 规定了空行的使用方式:

空行

在顶层的函数和类定义之间要用两个空行分开。

在一个类里面的方法定义之间用一个空行分开。

可以适当地使用额外的空行来分隔相关的函数组。对于一组相关的单行函数(比如一些占位符实现),可以不使用空行。

在函数内部,可以适当地使用空行来表示逻辑上的不同部分。

Python 允许使用控制字符L(也就是 ^L)作为空白字符;很多工具会把这些字符当作页面分隔符,所以你可以用它们来分隔文件中相关部分的页面。不过要注意,有些编辑器和网页代码查看器可能不识别控制字符L,可能会显示成其他符号。

如果你遵循PEP 8,唯一可能在交互式控制台中引起问题的情况就是“在函数中使用空行来表示逻辑部分”,我认为。

不过你可以这样避免这个问题:

>>> def a():
...     print 'foo'\
...
...     print 'bar'
...
>>> a()
foo
bar

注意,使用 \ 而不是 #,就像你在问题中提到的那样,会让空行保持为空(因为 \ 会放在 前一行)。

撰写回答