我有一个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
这些错误意味着什么?我做错了什么?我如何修复我的代码?
**注意:**这是一个canonical question的尝试,因为我每个月都会看到很多类似的帖子。这不是关于unindents或unexpected indents的现有问题的重复,因为它们只处理一种类型的缩进错误,我希望在一个地方涵盖它们。
也有可能出现逻辑上不正确的缩进,但不会导致错误消息。一种常见的形式是将else:
附加到for
或while
循环中,而不是(如预期的那样)相应的if:
。如果需要关闭问题,请参阅Else clause on Python while statement。
请参阅How to fix Python indentation,了解更多清理缩进以符合标准的工具和技术(即使它已经“工作”)。
6条答案
按热度按时间laximzn51#
为什么缩进很重要?
在Python中,缩进用于分隔blocks of code。这与许多其他使用花括号
{}
分隔块的语言(如Java,Javascript和C)不同。因此,Python用户必须密切注意何时以及如何缩进代码,因为空格很重要。当Python遇到程序缩进问题时,它会引发一个名为
IndentationError
或TabError
的异常。一段历史
Python使用缩进而不是更普遍接受的花括号
{}
的历史原因在an article of the history of Python by Guido van Rossum中概述-Python的创建者:Python对缩进的使用直接来自ABC,但这个想法并不是ABC的原创--它已经由Donald Knuth推广,是一个众所周知的编程风格概念。(occam编程语言也使用过)不过,ABC的作者确实发明了冒号的使用,它将导入子句与缩进块分开,在早期的用户测试中没有使用冒号之后我们发现,对于刚开始学习编程的初学者来说,缩进的含义并不清楚。添加冒号后,缩进的含义变得清晰起来:冒号以某种方式引起了人们对后面内容的注意,并以正确的方式将它之前和之后的短语联系在一起。
如何缩进代码?
缩进Python代码的基本规则(考虑到您将整个程序视为“基本块”)是:基本块中的第一个语句以及其后的每个语句必须缩进相同的数量。
所以从技术上讲,下面的Python程序是正确的:
然而,正如你可能从上面看到的,随机缩进代码会使你的代码难以阅读和遵循程序的流程,最好保持一致并遵循一种风格。
PEP 8 -Python风格指南-说:
每个缩进级别使用4个空格。
也就是说,每个开始新块的语句和新块中的每个后续语句,都应该从当前缩进级别缩进四个空格。下面是根据PEP 8样式指南缩进的上述程序:
标签页还能用吗?
Python意识到有些人仍然喜欢制表符而不是空格,并且遗留代码可能使用制表符而不是空格,因此它允许使用制表符作为缩进。PEP 8涉及到这个主题:
空格是首选的缩进方法。
制表符只能用于与已使用制表符缩进的代码保持一致。
注意,一个很大的警告是不要同时使用制表符 * 和 * 空格进行缩进。这样做会导致各种奇怪的难以调试的缩进错误。Python expands tabs to the next 8th column,但是如果你的编辑器设置为4列的制表符大小,或者你使用空格和制表符,你可以很容易地产生缩进代码,在你的编辑器中看起来很好。但Python会拒绝运行。Python 3编译器 * 显式 * 拒绝任何包含不明确的制表符和空格混合的程序,通常是通过引发
TabError
。然而,默认情况下,Python 2仍然允许混合制表符和空格,但强烈建议不要使用这个“特性”。使用-t
和-tt
命令行标志来强制Python 2分别引发警告或(最好)错误。PEP 8也讨论了这个主题:Python 3不允许在缩进中混合使用制表符和空格。
Python 2代码中混合使用制表符和空格的缩进应该转换为只使用空格。
当使用-t选项调用Python 2命令行解释器时,它会发出关于非法混合制表符和空格的代码的警告。当使用-tt时,这些警告会变成错误。强烈推荐使用这些选项!
“缩进错误:意外缩进”是什么意思
问题
当一个语句被不必要地缩进或其缩进与同一块中以前语句的缩进不匹配时,就会发生此错误。例如,下面程序中的第一个语句被不必要地缩进:
在本例中,
if
块中的can_drive = True
行与前面任何语句的缩进都不匹配:修复
修复此错误的方法是首先确保有问题的行甚至需要缩进。例如,上面使用
print
的示例可以简单地通过取消缩进行来修复:然而,如果你确定这一行确实需要缩进,缩进需要与同一块中的前一个语句的缩进相匹配。在上面使用
if
的第二个例子中,我们可以通过确保can_drive = True
的行与if
主体中的前一个语句缩进在同一级别来修复错误:“缩进错误:预期缩进块”是什么意思
(This在Python 3.8或更低版本中也可能出现为
SyntaxError: unexpected EOF while parsing
。)问题
当Python看到一个复合语句的“头”,比如
if <condition>:
或while <condition>:
,但复合语句的主体或***块***从未定义时,就会发生这个错误。例如,在下面的代码中,我们开始了一个if
语句,但我们从未定义该语句的主体:在第二个例子中,我们开始编写一个
for
循环,但是我们忘记了缩进for
循环体。所以Python仍然期望for
循环体的缩进块:注解不算作正文:
修复
此错误的修复方法是简单地包含复合语句的主体。
如上所示,新用户的一个常见错误是他们忘记缩进主体。如果是这种情况,请确保要包含在复合语句主体中的每个语句都在复合语句开头的同一级别缩进。下面是上面的示例修复:
另一种常见的情况是,出于某种原因,用户可能不想为复合语句定义实际的主体,或者主体可能被注解掉。在这种情况下,可以使用
pass
语句。pass
语句可以在Python需要一个或多个语句作为占位符的任何地方使用。从pass
的文档中可以看到:pass是一个null操作-当它被执行时,什么都不会发生。当语法上需要一个语句,但不需要执行任何代码时,它作为占位符很有用,例如:
下面是上面的示例,其中使用
pass
关键字修复了if
语句:“缩进错误:unindent不匹配任何外部缩进级别”是什么意思?
问题
当您取消缩进一个语句,但现在该语句的缩进级别与之前任何语句的缩进级别都不匹配时,就会发生此错误。例如,在下面的代码中,我们取消缩进第二个对
print
的调用。但是,缩进级别与之前任何语句的缩进级别都不匹配:这个错误很难捕捉,因为即使是一个空格也会导致代码失败。
修复
修复方法是确保在取消缩进语句时,缩进级别与前一个语句的缩进级别相匹配。再次考虑上面的示例。在示例中,我希望第二次调用print位于第一个
if
语句体中。因此,我需要确保该行的缩进级别与第一个if
语句体中的前一个语句的缩进级别相匹配:我仍然收到IndentationError,但我的程序似乎正确缩进。我该怎么办?
如果你的程序在视觉上看起来有正确的缩进,但你仍然得到一个
IndentationError
,你很可能有混合的制表符和空格。这有时会导致Python引发奇怪的错误。请参阅小节***特殊情况***下***什么是“TabError:缩进中制表符和空格的使用不一致”意味着?***对问题进行了更深入的解释。“TabError:缩进中制表符和空格的使用不一致”是什么意思?
问题
这个错误只会在你尝试将制表符和空格混合作为缩进字符时发生。如上所述,Python不允许你的程序包含制表符和空格的混合,如果它发现你有,它会引发特定的异常
TabError
。例如,在下面的程序中,制表符和空格的混合用于缩进:下面的图片直观地显示了上面程序中的空白。灰色的点是空格,灰色的箭头是制表符:
我们可以看到,我们确实混合了空格和制表符用于缩进。
特殊情况
注意如果你在程序中混合使用制表符和空格,Python***不会***总是 * 引发
TabError
。如果程序缩进是明确的,Python将允许制表符和空格混合使用。例如:有时候Python会因为制表符和空格的混合而阻塞,错误地抛出
IndentationError
异常,而TabError
更合适。另一个例子:正如你所看到的,以这种方式运行你的代码可能会产生神秘的错误。即使程序 * 在视觉上 * 看起来很好,Python在试图解析用于缩进的制表符和空格时会感到困惑,并出错。
这些都是很好的例子,演示了为什么在使用Python 2时,永远不要混合使用制表符和空格,并使用
-t
和-tt
解释器标志。修复
如果你的程序很短,可能最简单和最快的解决方法就是简单地重新缩进程序。确保每个语句在每个缩进级别缩进四个空格(参见***如何缩进代码?***)。
但是,如果你已经有一个混合了制表符和空格的大型程序,那么可以使用自动化工具将所有缩进转换为空格。
许多编辑器,如PyCharm和SublimeText都有自动将制表符转换为空格的选项。还有一些在线工具,如Tabs To Spaces或Browserling,可以让你快速重新缩进代码。还有一些用Python编写的工具。例如,autopep8可以自动重新缩进代码并修复其他缩进错误。
即使是最好的工具,有时也不能修复所有的缩进错误,你必须手动修复它们。这就是为什么从一开始就正确缩进你的代码是很重要的。
关于“SyntaxError”相关缩进问题的说明
虽然不经常,但有时由于不正确的缩进会引发某些
SyntaxError
异常。例如,请看下面的代码:当上面的代码运行时,会引发
SyntaxError
:虽然Python抛出了一个
SyntaxError
,但上面代码的真实的问题是第二个pass
语句应该缩进。因为第二个pass
不是缩进的,所以Python没有意识到前面的if
语句和else
语句是要连接的。解决这类错误的方法是正确地重新缩进代码。要了解如何正确缩进代码,请参阅***如何缩进代码?***一节。
Python的缩进语法我还是不太懂,怎么办?
如果你还在挣扎,不要气馁。习惯Python的空格语法规则可能需要时间。这里有一些提示可以帮助你:
使用资源
wsewodh22#
Sublime Text 3
如果您使用Sublime Text 3编写代码,这可以帮助您解决缩进问题
在Sublime Text中,编辑Python文件时:
Sublime Text菜单〉首选项〉设置-特定语法:
Python.sublime-settings
voase2hg3#
你看,你有一个小错误。
你应该做:
正如你所看到的,你的打印只缩进了3个空格,它应该缩进4个空格。
zte4gxcn4#
Python 2历史说明
默认情况下,Python 2允许制表符和空格混合使用,并且默认情况下不会产生错误。将
-tt
选项传递给Python 2.x会导致它在3.x相同的情况下引发异常,而-t
会导致警告。完整的细节在Python's interpretation of tabs and spaces to indent中解释。特别要注意的是,制表符被视为8空格(相反,它们有效地将感知到的空格数增加到8的下一个倍数)。因此,如果您使用标准的4空格缩进来显示代码,但混合了空格和制表符,您最终可能会得到 * 满足缩进规则的代码,但不会被认为是以与外观相同的方式缩进 *。
因此,您可能会得到 * 各种其他错误 *。例如:
(Note Stack Overflow的Markdown渲染will show the indentation as spaces even if I use tabs。
这样就得到了一个
NameError
,因为print x
不再在nested
函数内部,而x
超出了外部example
的作用域。类似地,我们可以通过给example
一个本地x = 1
来轻松创建一个TypeError
,或者通过给它一个本地x = []
来创建ValueError
。wrrgggsh5#
快速检查表
IndentationError
,但也可能导致TabError
(IndentationError
的子类型)或SyntaxError
(缩进本身是法律的的,但它会导致其他代码出现语法错误)。对于Python代码有效但不符合程序员意图的缩进会导致逻辑错误(代码不会引发异常,但会出错)。*强烈建议不要使用制表符进行缩进。在Python 2.x中,使用
-tt
命令行参数运行Python会引发相同的TabError
,这对查找问题很有用。if
、for
、def
和class
这样以冒号:
结尾的语句,后面需要一个 * 缩进块 *:pass
语句:while
和for
循环可能有anelse
clause, which executes if the loop complete normally rather than viabreak
。这是逻辑错误的常见来源:2ledvvac6#
Sublime用户的快速修复:
1.按Ctrl-H访问“查找和替换”
1.在查找中:键入4个空格
1.替换:从代码中的某处复制并粘贴选项卡单击“全部替换”