我收到一个 IndentationError。我如何解决它?

新手上路,请多包涵

我有一个 Python 脚本:

 if True:
    if False:
        print('foo')
   print('bar')

但是,当我尝试运行我的脚本时,Python 引发了一个 IndentationError

   File "script.py", line 4
    print('bar')
               ^
IndentationError: unindent does not match any outer indentation level

我一直在玩我的程序,总共产生了四个错误:

  • IndentationError: unexpected indent
  • IndentationError: expected an indented block
  • TabError: inconsistent use of tabs and spaces in indentation
  • IndentationError: unindent does not match any outer indentation level

这些错误是什么意思?我究竟做错了什么?我该如何修复我的代码?


注意: 这是对 规范问题 的尝试,因为我每个月都会看到很多类似的帖子。这不是关于 未缩进意外缩进 的现有问题的重复,因为它们每个只处理一种类型的缩进错误,我希望在一个地方涵盖所有这些问题。

也可能出现 逻辑上 不正确的缩进, 但不会 导致出现错误消息。 One common form of this is attaching else: to a for or while loop rather than (as intended) the corresponding if: .如果您需要关闭 OP 所做的问题,请参阅 Python while 语句中的 Else 子句

原文由 Christian Dean 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.4k
2 个回答

为什么缩进很重要?

在 Python 中,缩进用于分隔 代码块。这不同于许多其他使用大括号 {} 来分隔块的语言,例如 Java、Javascript 和 C。因此,Python 用户必须密切注意他们何时以及如何缩进代码,因为空格事项。

当 Python 遇到程序缩进问题时,它会引发名为 IndentationErrorTabError 的异常。

一点历史

Python 使用缩进与可以说更普遍接受的花括号的历史原因 {} 在 Python 的创造者 Guido van Rossum 的 Python 历史文章中 概述:

Python 对缩进的使用直接来自 ABC,但这个想法并非源自 ABC——它已经被 Donald Knuth 推广,并且是一种众所周知的编程风格概念。 (occam 编程语言也使用它。)但是,ABC 的作者确实发明了冒号的使用,将引导子句与缩进块分开。在没有冒号的早期用户测试后,发现对于正在学习编程第一步的初学者来说,缩进的含义并不明确。冒号的加入明显地澄清了这一点:冒号以某种方式引起了人们对后面内容的注意,并以正确的方式将其前后的短语联系在一起。

如何缩进我的代码?

缩进 Python 代码的基本规则(考虑到您将整个程序视为“基本块”)是:基本块中的第一条语句及其后的每个后续语句必须缩进相同的量。

所以从技术上讲,以下 Python 程序是正确的:

 def perm(l):
        # Compute the list of all permutations of l
    if len(l) <= 1:
                  return [l]
    r = []
    for i in range(len(l)):
             s = l[:i] + l[i+1:]
             p = perm(s)
             for x in p:
              r.append(l[i:i+1] + x)
    return r

然而,正如您可能从上面看出的那样,随机缩进您的代码使得阅读和遵循程序流程变得非常困难。最好保持一致并遵循一种风格。

PEP 8——Python 风格指南——说

每个缩进级别使用 4 个空格。

也就是说, 开始新块的每个语句和新块中的每个后续语句都应从当前缩进级别缩进四个空格。以下是根据 PEP8 风格指南缩进的上述程序:

 def perm(l):
    # Compute the list of all permutations of l
    if len(l) <= 1:
        return [l]
    r = []
    for i in range(len(l)):
        s = l[:i] + l[i+1:]
        p = perm(s)
        for x in p:
            r.append(l[i:i+1] + x)
    return r

我还能使用标签吗?

Python 意识到有些人仍然更喜欢制表符而不是空格,并且遗留代码可能使用制表符而不是空格,因此它允许使用制表符作为缩进。 PEP8 涉及到这个话题

空格是首选的缩进方法。

制表符应仅用于与已经使用制表符缩进的代码保持一致。

但是请注意,一个重要的警告是 不要同时使用制表符 空格进行缩进。这样做会导致各种奇怪的难以调试的缩进错误。 Python 将制表符扩展到下一个第 8 列,但是如果您的编辑器将制表符大小设置为 4 列,或者您使用空格和制表符,您可以轻松地生成在编辑器中 看起来 不错的缩进代码,但 Python 会拒绝跑步。 Python 3 编译器 明确 拒绝任何包含制表符和空格的模糊混合的程序,通常是通过引发 TabError 。然而,默认情况下,Python 2 仍然允许混用制表符和空格,但强烈建议不要使用此“功能”。使用 -t-tt 命令行标志强制 Python 2 分别发出警告或(最好)错误。 PEP8 也讨论了这个话题

Python 3 不允许混合使用制表符和空格进行缩进。

混合使用制表符和空格缩进的 Python 2 代码应转换为仅使用空格。

使用 -t 选项调用 Python 2 命令行解释器时,它会发出有关非法混合制表符和空格的代码的警告。使用 -tt 时,这些警告会变成错误。强烈推荐这些选项!

“IndentationError:意外缩进”是什么意思?

问题

当语句不必要地缩进或其缩进与同一块中先前语句的缩进不匹配时,会发生此错误。例如,下面程序中的第一条语句不必要地缩进:

 >>>  print('Hello') # this is indented
  File "<stdin>", line 1
    print('Hello') # this is indented
    ^
IndentationError: unexpected indent

在此示例中, if 块中的 can_drive = True 行与任何先前语句的缩进不匹配:

 >>> age = 10
>>> can_drive = None
>>>
>>> if age >= 18:
...     print('You can drive')
...      can_drive = True # incorrectly indented
  File "<stdin>", line 3
    can_drive = True # incorrectly indented
    ^
IndentationError: unexpected indent

使固定

此错误的修复是首先确保有问题的行甚至需要缩进。例如,上面使用 print 的示例可以通过取消缩进来修复:

 >>> print('Hello') # simply unindent the line
Hello

但是,如果您确定该行确实需要缩进,则缩进需要与同一块中前一条语句的缩进相匹配。在上面使用 if 的第二个示例中,我们可以通过确保带有 can_drive = True if 身体:

 >>> age = 10
>>> can_drive = None
>>>
>>> if age >= 18:
...     print('You can drive')
...     can_drive = True # indent this line at the same level.
...

“IndentationError: expected an indented block”是什么意思?

(这也可能在 Python 3.8 或更低版本中作为 SyntaxError: unexpected EOF while parsing 出现。)

问题

当 Python 看到复合语句的“标头”时会发生此错误,例如 if <condition>:while <condition>: 但从未定义复合语句的主体或 。例如,在下面的代码中,我们开始了一个 if 语句,但我们从未为该语句定义主体:

 >>> if True:
...
  File "<stdin>", line 2

    ^
IndentationError: expected an indented block

在第二个示例中,我们开始编写 for 循环,但我们忘记缩进 for 循环体。所以 Python 仍然需要 for 循环体的缩进块:

 >>> names = ['sarah', 'lucy', 'michael']
>>> for name in names:
... print(name)
  File "<stdin>", line 2
    print(name)
        ^
IndentationError: expected an indented block

评论不算作正文:

 >>> if True:
...     # TODO
...
  File "<stdin>", line 3

    ^
IndentationError: expected an indented block

使固定

解决此错误的方法是简单地包含复合语句的主体。

如上所示,新用户的一个常见错误是他们忘记缩进正文。如果是这种情况,请确保要包含在复合语句正文中的每个语句都缩进到复合语句开头下方的同一级别。这是上面的示例修复:

 >>> names = ['sarah', 'lucy', 'michael']
>>> for name in names:
...     print(name) # The for loop body is now correctly indented.
...
sarah
lucy
michael

另一种常见情况是,出于某种原因,用户可能不想为复合语句定义实际主体,或者主体可能被注释掉。在这种情况下,可以使用 pass 语句。 pass 语句可以在 Python 期望一个或多个语句作为占位符的任何地方使用。 pass 的文档中

pass 是一个空操作——当它被执行时,什么也不会发生。当语法上需要一条语句但不需要执行任何代码时,它可用作占位符,例如:

>  def f(arg): pass    # a function that does nothing (yet)
>
> class C: pass       # a class with no methods (yet)
>
> ```

这是上面的示例,其中 `if` 语句通过使用 `pass` 关键字修复:

if True: … pass # We don’t want to define a body. …


## “IndentationError: unindent does not match any outer indentation level”是什么意思?

**问题**

当您取消缩进语句时会发生此错误,但现在该语句的缩进级别与任何先前语句的缩进级别都不匹配。例如,在下面的代码中,我们取消了对 `print` 的第二次调用。但是,缩进级别与之前的任何语句都不匹配:

if True: … if True: … print(‘yes’) … print() File “”, line 4 print() ^ IndentationError: unindent does not match any outer indentation level


这个错误特别难以捕捉,因为即使是一个空格也会导致您的代码失败。

**使固定**

修复是为了确保当您取消缩进语句时,缩进级别与前一个语句的缩进级别相匹配。再次考虑上面的例子。在示例中,我希望第二次调用打印在第一个 `if` 语句主体中。所以我需要确保该行的缩进级别与第一个 `if` 语句主体中的前一个语句的缩进级别相匹配:

if True: … if True: … print(‘yes’) … print() # indentation level now matches former statement’s level. … yes


## 我仍然收到 IndentationError,但我的程序似乎已正确缩进。我该怎么办?

如果你的程序在视觉上看起来有正确的缩进,但你仍然得到 `IndentationError` 你很可能 **混合了制表符和空格**。这有时会导致 Python 引发奇怪的错误。请参阅 **_“TabError:缩进中制表符和空格的使用不一致”是什么意思_** 下的 **_特殊情况_** 小节?以获得对问题的更深入的解释。

## “TabError:缩进中制表符和空格的使用不一致”是什么意思?

**问题**

仅当您尝试混合使用制表符和空格作为缩进字符时才会发生此错误。如上所述,Python 不允许您的程序包含制表符和空格的混合,如果发现有,则会引发特定异常 `TabError` 。例如,在下面的程序中,制表符和空格混合用于缩进:

if True: … if True: … print() … print() … print() File “”, line 5 print() ^ TabError: inconsistent use of tabs and spaces in indentation


这是一张图片,直观地显示了上述程序中的空白。灰色点是空格,灰色箭头是制表符:

[![在此处输入图像描述](https://i.stack.imgur.com/pFV48.png)](https://i.stack.imgur.com/pFV48.png)

我们可以看到我们确实混合了缩进的空格和制表符。

**特别案例**

注意如果您在程序中混合制表符和空格,Python **_不会_** _总是_ 引发 `TabError` 。如果程序缩进没有歧义,Python 将允许制表符和空格混用。例如:

if True: … if True: # tab … pass # tab, then 4 spaces …


有时 Python 会因制表符和空格的混合而窒息,并错误地引发 `IndentationError` 异常,而 `TabError` 更合适。另一个例子:

if True: … pass # tab … pass # 4 spaces File “”, line 3 pass # 4 spaces ^ IndentationError: unindent does not match any outer indentation level


如您所见,以这种方式运行代码会产生神秘的错误。尽管该程序在 _视觉上_ 看起来不错,但 Python 在尝试解析用于缩进的制表符和空格时变得混乱并出错。

这些都是很好的例子,说明为什么在使用 Python 2 时永远不要混合制表符和空格并使用 `-t` 和 `-tt` 解释器标志。

**使固定**

如果您的程序很短,最简单和最快捷的修复方法可能就是简单地重新缩进程序。确保每条语句在每个缩进级别缩进四个空格(请参阅 **_如何缩进我的代码?_** )。

但是,如果您已经有一个混合了制表符和空格的大型程序,则可以使用自动化工具将所有缩进转换为空格。

[PyCharm](https://www.jetbrains.com/pycharm/) 和 [SublimeText](https://www.sublimetext.com/) 等许多编辑器都有自动将制表符转换为空格的选项。还有一些在线工具,例如 [Tabs To Spaces](http://tabstospaces.com/) 或 [Browserling](https://www.browserling.com/tools/tabs-to-spaces) ,可让您快速重新缩进代码。还有一些用 Python 编写的工具。例如, [autopep8](https://github.com/hhatto/autopep8) 可以自动重新缩进您的代码并修复其他缩进错误。

即使是最好的工具有时也无法修复所有的缩进错误,您必须手动修复它们。这就是为什么从一开始就始终正确缩进代码很重要。

## 关于“SyntaxError”相关缩进问题的说明

虽然不经常,但有时某些 `SyntaxError` 由于缩进不正确而引发异常。例如,看下面的代码:

if True: pass pass # oops! this statement should be indented!. else: pass


运行上述代码时,将引发 `SyntaxError` :

Traceback (most recent call last): File “python”, line 4 else: ^ SyntaxError: invalid syntax

”`

虽然 Python 提出了一个 SyntaxError ,但上面代码的 真正 问题是第二个 pass 语句应该缩进。因为第二个 pass 没有缩进,Python 没有意识到前面的 if 语句和 else 语句意味着连接。

解决此类错误的方法是简单地正确地重新缩进您的代码。要了解如何正确缩进代码,请参阅 如何缩进代码? .

我仍然很难使用 Python 的缩进语法。我该怎么办?

如果你还在挣扎,不要气馁。习惯 Python 的空格语法规则可能需要时间。以下是一些有用的提示:

  • 找一个编辑器,当你有缩进错误时它会告诉你。上面说的一些商品是 PyCharmSublimeTextJupyter Notebook
  • 缩进代码时,请自己大声数出按空格键(或 Tab 键)的次数。例如,如果您需要将一行缩进四个空格,您可以大声说出“ _一_、 _二_、 _三_、 _四_”,同时每次都同时按下空格键。这听起来很傻,但它有助于训练您的大脑思考您将代码缩进了多深。
  • 如果您有编辑器,请查看它是否有自动将制表符转换为空格的选项。
  • 查看别人的代码。浏览 githubStackoverflow 并查看 Python 代码示例。
  • 只写代码。这是变得更好的唯一最佳方法。你写的 Python 代码越多,你就会越好。

使用的资源

原文由 Christian Dean 发布,翻译遵循 CC BY-SA 4.0 许可协议

崇高文本 3

如果碰巧你在 Sublime Text 3 中编码,这可以帮助你解决缩进问题

在 Sublime Text 中编辑 Python 文件时:

Sublime Text 菜单 > 首选项 > 设置 - 语法特定

Python.sublime 设置

{
    "tab_size": 4,
    "translate_tabs_to_spaces": true
}

原文由 chebaby 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题