在Python 3解释器模式下粘贴代码时出现IndentationError

Jia*_* Xu 3 python

当我运行以下代码时,这些代码在函数内部具有空白行(无空格),在解释器模式下逐行运行代码时,我得到的行为与Python 3.6.5不同python3 split.py:

# File split.py

def find(s, start, predictor):
    for i in range(start, len(s)):
        if predictor(s[i]):
            return i
    return -1

def find_all(s, sep=" \t\n"):
    beg_of_nonsep = 0
    while beg_of_nonsep < len(s):
        beg_of_nonsep = find(s, beg_of_nonsep, lambda ch, sep_chs=sep: ch not in sep_chs)
        if beg_of_nonsep == -1:
            break

        end_of_nonsep = find(s, beg_of_nonsep + 1, lambda ch, sep_chs=sep: ch in sep_chs)
        if end_of_nonsep == -1:
            end_of_nonsep = len(s)

        yield (beg_of_nonsep, end_of_nonsep)

        beg_of_nonsep = end_of_nonsep + 1

split = lambda s: [s[beg: end] for (beg, end) in find_all(s)]

print(split(""))
print(split("     \t\n"))
print(split("     \tssss\n"))
Run Code Online (Sandbox Code Playgroud)

在解释器模式下逐行运行代码时,出现python3了一些讨厌的错误:

Type "help", "copyright", "credits" or "license" for more information.
>>> def find(s, start, predictor):
...     for i in range(start, len(s)):
...         if predictor(s[i]):
...             return i
...     return -1
...
>>> def find_all(s, sep=" \t\n"):
...     beg_of_nonsep = 0
...     while beg_of_nonsep < len(s):
...         beg_of_nonsep = find(s, beg_of_nonsep, lambda ch, sep_chs=sep: ch not in sep_chs)
...         if beg_of_nonsep == -1:
...             break
...
>>>         end_of_nonsep = find(s, beg_of_nonsep + 1, lambda ch, sep_chs=sep: ch in sep_chs)
  File "<stdin>", line 1
    end_of_nonsep = find(s, beg_of_nonsep + 1, lambda ch, sep_chs=sep: ch in sep_chs)
    ^
IndentationError: unexpected indent
>>>         if end_of_nonsep == -1:
  File "<stdin>", line 1
    if end_of_nonsep == -1:
    ^
IndentationError: unexpected indent
>>>             end_of_nonsep = len(s)
  File "<stdin>", line 1
    end_of_nonsep = len(s)
    ^
IndentationError: unexpected indent
>>>
>>>         yield (beg_of_nonsep, end_of_nonsep)
  File "<stdin>", line 1
    yield (beg_of_nonsep, end_of_nonsep)
    ^
IndentationError: unexpected indent
>>>
>>>         beg_of_nonsep = end_of_nonsep + 1
  File "<stdin>", line 1
    beg_of_nonsep = end_of_nonsep + 1
    ^
IndentationError: unexpected indent
>>>
>>> split = lambda s: [s[beg: end] for (beg, end) in find_all(s)]
>>>
>>> print(split(""))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
TypeError: 'NoneType' object is not iterable
>>> print(split("     \t\n"))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
TypeError: 'NoneType' object is not iterable
>>> print(split("     \tssss\n"))



Run Code Online (Sandbox Code Playgroud)

而print这里的最后一个永远不会退出,直到我习惯ctrlc停止它为止。

因此,我认为我的代码存在许多错误。

但是,当我使用来运行代码时python3 split.py,这些都没有发生:

[]
[]
['ssss']
Run Code Online (Sandbox Code Playgroud)

这让我很困惑。

需要明确的是,我实际上是在Debian 9.8和vim 8.1上使用vimcmdline。

我也使用pylintthrough pymode,它分割了任何多余的尾随空间。

当我尝试使用其内置的键绑定将其发送split.py到打开python3的tmux拆分中时,发生了此问题。

我已经解决了一个问题,但我不禁怀疑为什么python3会这样。

Phi*_*ing 19

这种行为在我看来并不奇怪。

Python使用缩进来确定代码块的开头和结尾。逻辑上缩进在未缩进的第一行上结束。运行脚本时,空行将被忽略。而且,当运行脚本时,这意味着缩进以无缩进行或文件结尾结束。

但是,此行为在命令行模式下不起作用,因为没有文件结尾。考虑以下脚本文件:

from somewhere import bar, do_something

for foo in bar:
    do_something(foo)
Run Code Online (Sandbox Code Playgroud)

在脚本中,文件末尾指示它现在应该运行for循环。它知道没有更多要执行的了。但是在命令行模式下,命令行仍处于打开状态,您仍然可以编写更多内容。不知道下一行代码是在for循环内还是在for循环外。但是命令行不能只坐着等待下一行代码……您希望它立即执行……!

因此,命令行以一种特定的区别进行操作。空行也将结束代码块。所以这很好:

from somewhere import bar, do_something, do_something_else

for foo in bar:
    do_something(foo)
    do_something_else(foo)
Run Code Online (Sandbox Code Playgroud)

但这是一个错误:

from somewhere import bar, do_something, do_something_else

for foo in bar:
    do_something(foo)

    do_something_else(foo)
Run Code Online (Sandbox Code Playgroud)

因为您已经用空白行结束了for循环,因此无法将其添加到循环中。

  • 这是一个很好的解释。值得注意的是,解释器_could_的设计使其始终等待不缩进的行,这实际上意味着,当您希望它“执行…现在!”时,您应该键入不缩进的“ pass”。大概所有这些额外的“通过”被认为比与实际语言不兼容更令人讨厌。 (4认同)