我收到一个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:意外缩进”
  • “IndentationError:预计一个缩进块”
  • “TabError:在缩进中使用制表符和空格不一致”

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

为什么缩进很重要?

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

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

有一点历史

Python的创build者Guido van Rossum在Python的历史文章中概述了为什么Python使用缩进与更普遍接受的大括号的历史原因{}

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

我如何缩进我的代码?

缩进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 

然而,正如你可以从上面说明的那样,随机缩进你的代码使得读取和跟踪程序stream程非常困难。 一致并遵循风格更好。

PEP8 – Python风格指南 – build议每个缩进级别使用四个空格 :

每个缩进级别使用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涉及这个话题 :

空格是首选的缩进方法。

选项卡应该仅用于与已经用选项卡缩进的代码保持一致。

但是请注意,一个重要的注意事项是不要同时使用制表符空格来缩进 。 这样做会导致各种奇怪的难以debugging的缩进错误。 Python 3编译器明确地拒绝任何包含制表符和空格混合的程序,通常通过引发TabError 。 不过,默认情况下,在Python 2中仍然允许混合制表符和空格,但强烈build议不要使用此“function”。 使用-t-tt命令行标志强制Python 2分别发出警告或(最好)错误。 PEP8还讨论了这个话题 :

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

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

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

“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:预计一个缩进块”是什么意思?

问题

当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是一个空操作 – 当它被执行时,什么都不会发生。 当语句需要语法时,它作为占位符是有用的,但是不需要执行代码,例如:

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

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

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

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

问题

这个错误发生在unindent语句的时候,但是现在这个语句的缩进级别和以前的语句的缩进级别不匹配。 例如,在下面的代码中,我们取消了第二个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引发奇怪的错误。 什么是“TabError:压缩中制表符和空格的不一致使用”是什么意思? 以便更深入地解释这个问题。

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

问题

只有当您尝试将制表符和空格混合为缩进字符时才会出现此错误。 如上所述,Python不会允许你的程序包含标签和空格的混合,并且如果发现你有程序会引发特定的exceptionTabError 。 例如,在下面的程序中,缩进使用了制表符和空格的组合:

 >>> if True: ... if True: ... print() ... print() ... print() File "<stdin>", line 5 print() ^ TabError: inconsistent use of tabs and spaces in indentation 

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

在这里输入图像描述

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

特殊情况

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

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

有时候,Python只是简单地混合了制表符和空格,当TabError更合适时,会错误地引发一个IndentationErrorexception。 另一个例子:

 >>> 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例如可以自动重新缩进您的代码和其他缩进错误。

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

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

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

  • 得到一个编辑器,当你有一个缩进错误时会告诉你。 有些商品如上所述,是PyCharm , SublimeText和Jupyter Notebook 。
  • 当你缩进你的代码时,你可以大声地对自己敲多less次按空格键(或tab键)。 例如,如果您需要将一行缩进四个空格,则每次同时按下空格键时,您会大声说出“ ”。 这听起来很愚蠢,但它有助于训练你的大脑思考你缩进代码的深度。
  • 如果您有编辑器,请查看是否有将标签自动转换为空格的选项。
  • 查看他人的代码。 浏览github或Stackoverflow并查看Python代码的示例。
  • 只需编写代码。 这是改善的最好方法。 你写的Python代码越多,你就会越好。

使用的资源

  • python的time.sleep()有多准确?
  • 我想exception处理“列表索引超出范围”。
  • pandas写数据框到CSV文件
  • 如何在IntelliJ IDEA中使用制表符缩进?
  • Django的MultiValueDictKeyError错误,我如何处理它
  • Python中open和codecs.open的区别
  • 如何正确使用unit testing的assertRaises()与NoneType对象?
  • 计算Python列表中真正的布尔值的数量
  • 如何生成Google Analytics的访问者stream量图表/图表?
  • PANDAS绘制多个Y轴
  • 提取float / double值