关于python:我得到一个IndentationError。 我如何解决它?

I'm getting an IndentationError. How do I fix it?

我有一个Python脚本:

1
2
3
4
if True:
    if False:
        print('foo')
   print('bar')

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

1
2
3
4
  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

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


为什么压痕很重要?

在Python中,缩进用于分隔代码块。这与使用花括号{}来划分诸如Java,Javascript和C等块的许多其他语言不同。因此,Python用户必须密切关注它们何时以及如何缩进其代码,因为空白很重要。

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

有点历史

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

Python’s use of indentation comes directly from ABC, but this idea didn’t originate with ABC--it had already been promoted by Donald Knuth and was a well-known concept of programming style. (The occam programming language also used it.) However, ABC’s authors did invent the use of the colon that separates the lead-in clause from the indented block. After early user testing without the colon, it was discovered that the meaning of the indentation was unclear to beginners being taught the first steps of programming. The addition of the colon clarified it significantly: the colon somehow draws attention to what follows and ties the phrases before and after it together in just the right way.

Ok.

如何缩进我的代码?

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

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

1
2
3
4
5
6
7
8
9
10
11
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

但是,正如您可能从上面可以看出的那样,随机缩进您的代码使得极难阅读并遵循程序流程。最好是保持一致并遵循一种风格。

PEP8 - Python样式指南 - 建议每个缩进级别应使用四个空格:

Use 4 spaces per indentation level.

Ok.

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

1
2
3
4
5
6
7
8
9
10
11
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 disallows mixing the use of tabs and spaces for indentation.

Ok.

Python 2 code indented with a mixture of tabs and spaces should be converted to using spaces exclusively.

Ok.

When invoking the Python 2 command line interpreter with the -t option, it issues warnings about code that illegally mixes tabs and spaces. When using -tt these warnings become errors. These options are highly recommended!

Ok.

"IndentationError:意外缩进"是什么意思?

问题

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

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

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

1
2
3
4
5
6
7
8
9
10
>>> 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的上述示例可以简单地修改为行:

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

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

1
2
3
4
5
6
7
>>> age = 10
>>> can_drive = None
>>>
>>> if age >= 18:
...     print('You can drive')
...     can_drive = True # indent this line at the same level.
...

"IndentationError:期望缩进块"是什么意思?

问题

当Python看到复合语句的"标题"时会发生此错误,例如if :while :,但从未定义复合语句的正文或块。例如,在下面的代码中,我们开始了一个if语句,但我们从不为语句定义一个主体:

1
2
3
4
5
6
>>> if True:
...
  File"<stdin>", line 2

    ^
IndentationError: expected an indented block

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

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

评论不算作正文:

1
2
3
4
5
6
7
>>> if True:
...     # TODO
...
  File"<stdin>", line 3

    ^
IndentationError: expected an indented block

固定

此错误的修复是简单地包含复合语句的主体。

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

1
2
3
4
5
6
7
>>> names = ['sarah', 'lucy', 'michael']
>>> for name in names:
...     print(name) # The for loop body is now correctly indented.
...
sarah
lucy
michael

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

pass is a null operation — when it is executed, nothing happens. It is useful as a placeholder when a statement is required syntactically, but no code needs to be executed, for example:

Ok.

1
2
3
def f(arg): pass    # a function that does nothing (yet)

class C: pass       # a class with no methods (yet)

以下是使用pass关键字修复if语句的上述示例:

1
2
3
4
>>> if True:
...     pass # We don't want to define a body.
...
>>>

"IndentationError:unindent与任何外部缩进级别不匹配"是什么意思?

问题

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

1
2
3
4
5
6
7
8
>>> if True:
...     if True:
...         print('yes')
...    print()
  File"<stdin>", line 4
    print()
          ^
IndentationError: unindent does not match any outer indentation level

此错误尤其难以捕获,因为即使一个空格也会导致代码失败。

固定

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

1
2
3
4
5
6
7
8
>>> if True:
...     if True:
...         print('yes')
...     print() # indentation level now matches former statement's level.
...
yes

>>>

我仍然得到一个IndentationError,但我的程序似乎正确缩进。我该怎么办?

如果您的程序在视觉上看起来有正确的缩进,但仍然得到IndentationError,则很可能混合使用空格。这有时会导致Python引发奇怪的错误。请参阅"TabError:缩进时标签和空格的不一致使用"是什么意思下的特殊情况?以便更深入地解释问题。

"TabError:缩进中标签和空格的不一致使用"是什么意思?

问题

仅当您尝试将制表符和空格混合为缩进字符时,才会出现此错误。如上所述,Python将不允许您的程序包含选项卡和空格的混合,并且如果它找到,将引发特定的异常TabError。例如,在下面的程序中,使用制表符和空格的混合来缩进:

1
2
3
4
5
6
7
8
9
>>> if True:
...     if True:
...         print()
...     print()
...     print()
  File"<stdin>", line 5
    print()
          ^
TabError: inconsistent use of tabs and spaces in indentation

这是一张可视化显示上述程序中的空白的图片。灰点是空格,灰色箭头是标签:

enter image description here

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

特别案例

注意如果将选项卡和空格混合到程序中,Python将不会始终引发TabError。如果程序缩进是明确的,Python将允许混合使用制表符和空格。例如:

1
2
3
4
5
>>> if True:
...     if True: # tab
...         pass # tab, then 4 spaces
...
>>>

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

1
2
3
4
5
6
7
>>> if True:
...     pass # tab
...     pass # 4 spaces
  File"<stdin>", line 3
    pass # 4 spaces
                ^
IndentationError: unindent does not match any outer indentation level

如您所见,以这种方式运行代码可能会产生神秘的错误。尽管程序在视觉上看起来很好,但是Python试图解析用于缩进和错误的选项卡和空格时感到困惑。

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

固定

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

但是,如果您已经有一个大型程序,您已将选项卡和空格混合在一起,则可以使用自动化工具将所有缩进转换为空格。

许多编辑器(如PyCharm和SublimeText)都可以选择自动将制表符转换为空格。还有一些在线工具,如Tabs To Spaces或Browserling,可以让您快速重新缩进代码。还有用P??ython编写的工具。例如,autopep8也可以自动重新缩进代码和其他缩进错误。

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

关于"SyntaxError"相关缩进问题的注释

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

1
2
3
4
5
if True:
    pass
pass # oops! this statement should be indented!.
else:
    pass

运行上面的代码时,SyntaxError is raised

1
2
3
4
5
Traceback (most recent call last):
  File"python", line 4
    else:
       ^
SyntaxError: invalid syntax

虽然Python引发了SyntaxError,但上面代码的真正问题是第二个pass语句应该缩进。因为第二个pass没有缩进,所以Python没有意识到先前的if语句和else语句是要连接的。

此类错误的修复方法是简单地正确重新缩进代码。要了解如何正确缩进代码,请参阅"如何缩进代码?"部分。

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

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

  • 获取一个编辑器,告诉您何时出现缩进错误。如上所述的一些商品是PyCharm,SublimeText和Jupyter Notebook。
  • 当您缩进代码时,请大声计算您按空格键(或Tab键)的次数。例如,如果你需要将一行缩进四个空格,你会大声说出"一,二,三,四",同时每次都按空格键。这听起来很愚蠢,但它有助于训练你的大脑思考你缩小代码的深度。
  • 如果您有编辑器,请查看它是否有自动将选项卡转换为空格的选项。
  • 查看其他人的代码。浏览github或Stackoverflow并查看Python代码示例。
  • 只需编写代码。这是变得更好的唯一最佳方式。编写Python代码越多,就越好。
  • 使用的资源

  • https://en.wikipedia.org/
  • https://docs.python.org/3/
  • http://python-history.blogspot.com/2009/02/early-language-design-and-development.html
  • https://www.python.org/dev/peps/pep-0008/
  • 好。


    崇高文本3

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

    在Sublime Text中,在编辑Python文件时:

    Sublime Text菜单> Preferences> Settings - Syntax Specific:

    Python.sublime的设置

    1
    2
    3
    4
    {
       "tab_size": 4,
       "translate_tabs_to_spaces": true
    }


    Sublime用户的快速修复:

  • 按Ctrl-H访问"查找和替换"
  • 在查找:类型4空格
  • 在替换中:从代码中的某处复制并粘贴选项卡
    单击全部替换

  • 你看,你有一个小错误。

    1
    2
    3
    4
    if True:
        if False:
            print('foo')
       print('bar')

    你应该这样做:

    1
    2
    3
    4
    if True:
        if False:
            print('foo')
        print('bar')

    正如您所看到的,您的打印仅缩进3个空格,它应该缩进4个空格。