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

时间:2017-08-10 19:06:52

标签: python exception error-handling indentation code-formatting

我有一个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

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

4 个答案:

答案 0 :(得分:52)

为什么缩进很重要?

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

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

一点历史

Python的创建者an article of the history of Python by 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

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

应该使用

PEP8 - The Python style guide - recommends that four spaces per indentation level

  

每个缩进级别使用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 touches on this topic

  

空格是首选的缩进方法。

     

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

但请注意,一个重要的警告是不要同时使用标签空格进行缩进。这样做会导致各种奇怪的难以调试缩进错误。 Python将选项卡扩展到下一个第8列,但如果您的编辑器设置为4列的选项卡大小,或者您使用空格和选项卡,则可以轻松生成看起来的缩进代码你的编辑器,但Python会拒绝运行。 Python 3编译器显式拒绝任何包含标签和空格混合的程序,通常是通过引发TabError。但是,默认情况下,Python 2中仍然允许混合制表符和空格,但强烈建议不要使用此功能&#34;。使用-t-tt命令行标志强制Python 2分别发出警告或(最好)错误。 PEP8 also discusses this topic

  

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

     

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

     

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

&#34; IndentationError:意外缩进&#34;意思?

<强>问题

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

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

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

>>> 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.
... 

什么&#34; IndentationError:期望缩进块&#34;意思?

<强>问题

当Python看到&#39;标题&#39;对于复合语句,例如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语句。可以在Python期望一个或多个语句作为占位符的任何地方使用pass语句。 From the documentation for 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.
... 
>>>

&#34; IndentationError:unindent与任何外部缩进级别都不匹配&#34;意思?

<强>问题

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

>>> if True:
...     if True:
...         print('yes')
...    print()
  File "<stdin>", 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引发奇怪的错误。请参阅 下面的 特殊情况 小节&#34; TabError:缩进中标签和空格的使用不一致&#34;意味着什么? 可以更深入地解释问题。

&#34; TabError:缩进中标签和空格的使用不一致&#34;意思?

<强>问题

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

>>> 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将允许混合使用制表符和空格。例如:

>>> if True:
...     if True: # tab
...         pass # tab, then 4 spaces
... 
>>>

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

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

正如您所看到的,以这种方式运行代码会产生神秘的错误。尽管程序 visual 看起来很好,但是Python试图解析用于缩进和错误的标签和空格时感到困惑。

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

<强>修正

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

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

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

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

关于&#34; SyntaxError&#34;的说明相关的缩进问题

尽管不常见,但由于缩进不正确,有时会引发某些SyntaxError异常。例如,请查看以下代码:

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

运行上述代码时,SyntaxError is raised

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键)的次数。例如,如果你需要将一行缩进四个空格,你会大声说出&#34; 一个两个三个 4 &#34;同时每次按空格键。这听起来很愚蠢,但它有助于训练你的大脑思考你的代码缩进程度。
  • 如果您有编辑器,请查看它是否有自动将标签转换为空格的选项。
  • 查看其他人&#39;码。浏览githubStackoverflow,查看Python代码示例。
  • 只需编写代码。这是改善的唯一最好方法。编写Python代码的次数越多,就越好。

使用的资源

答案 1 :(得分:2)

崇高文字3

如果您使用Sublime Text 3进行编码,则可以帮助您解决缩进问题

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

高级文本菜单 > 首选项 > 设置-特定于语法

Python.sublime-settings

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

答案 2 :(得分:0)

你看,你有一个小错误。

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

您应该这样做:

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

您可以看到您的打印仅缩进3个空格,应该缩进4个空格。

答案 3 :(得分:0)

Sublime用户的快速修复:

  1. 按Ctrl-H以访问“查找和替换”
  2. 在“查找”中:输入4个空格
  3. 在“替换”中:从代码中的某个位置复制并粘贴选项卡 点击全部替换