交互式提示符中的空白行规则

11

我想知道为什么在Python的交互式提示符和作为可执行文件从shell运行程序时,空行有不同的规则。

由于空行会被忽略,我喜欢频繁使用它们。然而,在交互提示符中,空行用于终止循环。因此,当我将一大块代码粘贴到交互提示符中时,我遇到了缩进错误,因为我的循环中会有空行。这使得交互式调试/开发过程有些繁琐。用#代替空行可以解决问题,但我喜欢我的空行。

更让人烦恼的是不同提示符之间的行为不同(例如python和ipython)。Python的交互提示符会在我期望的地方给出错误,而ipython则会保持执行缩进的代码,而不进行抱怨。

我觉得有一个简单的解决方案,但我不知道它。我正在使用vi编辑器和python/ipython提示符。谢谢。


2
问题在于,提示需要某种方式来确定您的输入何时结束,而空白行是迄今为止最简单的方式(最少麻烦)来实现这一点。 - user395760
你可能会对使用编辑器感兴趣,比如Emacs,它可以与交互式Python解释器通信。然后,你只需在草稿缓冲区中选择一块代码并批量执行即可。 - Michael Hoffman
一个解决方法是在代码块内的空白行上至少放置一个空格。 - jsbueno
谢谢您的评论。@jsbueno,不管出于什么原因,这对我来说不起作用。 - milancurcic
4个回答

4
因为解释器会在你按下回车键时尝试执行代码,但需要空行来确定函数、循环、条件语句或其他缩进块的结束位置。如果编写函数,则不需要(事实上也不起作用)在函数的最后一行之前添加空行。在这种情况下,空行是必需的,以表示函数的结尾。你可以在shell中执行没有空行的脚本。
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规则,因为在方法之前和之后需要一个空行。


确实。这是一个非常清晰的解释,谢谢。在提问时,我刚开始学习Python。从那时起就一直使用ipython。标准Python解释器逐行解析代码的行为在我看来是反特性。 - milancurcic
1
当然。我只是好奇如何保持我的文件与解释器兼容,最终来到了这个问题。最后,我决定回答它 :-) - Wyrmwood

3

PEP8定义了如何使用空行:

空行

使用两个空行来分隔顶层函数和类定义。类内方法定义之间用单个空行分隔。

可以使用额外的空行(适度地)来分隔相关函数组。在一些相关的单行实现之间可以省略空行(例如一组虚拟实现)。

在函数中适度使用空行来表示逻辑部分。

Python接受控制-L(即^L)换页符作为空格;许多工具将这些字符视为页面分隔符,因此您可以使用它们来分隔文件中相关部分的页面。请注意,某些编辑器和基于Web的代码查看器可能无法将控制-L识别为换页符,并显示另一个字形。

如果您遵循PEP,唯一可能在交互式控制台中出现问题的情况是“在函数中使用空行表示逻辑部分”,我想。

不过,您可以通过以下方式解决问题:

>>> def a():
...     print 'foo'\
... 
...     print 'bar'
... 
>>> a()
foo
bar
编辑:请注意,在您问题中建议使用\而非#,会使空白行保持为空白(因为\会放在上一行)。

希望对您有所帮助!


是的,这正是问题所在。我可以通过使用 # 来解决问题,而且像你建议的那样,\ 也可以起作用。 - milancurcic
1
@IRO-bot 与 # 的区别在于,如果你只有一个额外的空白行,你可以将 \ 放在前面一行(即留下下一行完全空白)。而使用 # 则不行。 - mac
谢谢!它在某种程度上确实有帮助-很好知道。我并不是真的在寻找一个可以改变语言特征的解决方法,而更多地是使用文本编辑器/解释器技巧来规避这个问题。无论如何,目前我发现使用#代替空行最方便-当我稍后删除空行时,您的解决方案会给我带来麻烦-需要同时删除\。 - milancurcic
@IRO-bot - 恭喜你,感谢你的选定和接受! ;) - mac
3
我喜欢 Python。但是,这个令人讨厌的缺陷——即解释模式和批处理模式之间不兼容的语法——使有经验和新手的 Python 程序员都感到沮丧。显然,将相同的正确代码粘贴到解释脚本的同一个程序中应该会产生相同的效果,然而 Python 即使到了 3.4 版本也没有满足这一期望。考虑到我与之合作过的几乎每个 Python 程序员都对此行为感到惊讶(很多人转而使用 IPython 来避免这种情况),Python 核心团队没有费心清理这一点是难以理解的。 - Alex North-Keys

1

ipython v5 现在可以很好地处理缩进的空白多行:

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

从上面的博客文章中: prompt_toolkit软件包是Jonathan Slenders开发的一个惊人的库,最近已经达到了1.0版本。除了readline之外,prompt_toolkit为在终端中编辑文本提供了许多高级功能,这显著改善了用户体验。由于它是一个跨平台库,所有Linux / Unix,macOS和Windows上的用户都受益于这些改进。由于prompt_toolkit,IPython现在支持:
- 输入时语法高亮 - 真正的多行编辑(上下箭头键在行之间移动) - 多行粘贴而不会破坏缩进或立即执行代码 - 更好的代码完成界面(我们计划进一步改进) - 可选鼠标支持

谢谢 - 这是一个惊人的、非常有帮助的新功能! - nealmcb

-1
如果您正在Unix系统上进行开发,请使用Sed!
为了在将代码粘贴到交互式提示符之前消除所有空行,请使用此命令:
sed '/^$/d' mysourcefile

sed是一种流编辑器。它以mysourcefile作为输入,然后将编辑后的文本发送到stdout。复制并粘贴输出到交互式Python shell中,你就可以开始了!
(或者使用Screen将编辑后的源代码发送到另一个屏幕会话,其中已打开交互式shell!)

循环和条件语句将失败。 - Wyrmwood

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