我有一个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
这些错误意味着什么?我究竟做错了什么?我该如何修复我的代码?
答案 0 :(得分:52)
在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程序是正确的:
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时,这些警告会出错。强烈推荐这些选项!
<强>问题强>
当语句不必要地缩进或其缩进与同一块中的前语句的缩进不匹配时,会发生此错误。例如,下面程序中的第一个语句不必要地缩进:
>>> 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.
...
<强>问题强>
当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.
...
>>>
<强>问题强>
当您取消注释语句时会发生此错误,但现在该语句的缩进级别与任何以前的语句的缩进级别不匹配。例如,在下面的代码中,我们取消了对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
您很可能带有空格的混合标签。这有时会导致Python引发奇怪的错误。请参阅 下面的 特殊情况 小节&#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
这是一张可视地显示上述程序中的空白的图片。灰点是空格,灰色箭头是标签:
我们可以看到确实混合了缩进的空格和制表符。
特殊情况
注意如果将标签和空格混合到程序中,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
解释器标记。
<强>修正强>
如果您的程序很短,可能最简单,最快捷的解决方法是简单地重新缩进程序。确保每个语句每个缩进级别缩进四个空格(参见 如何缩进我的代码? )。
但是,如果您已经有一个大型程序将选项卡和空格混合在一起,则可以使用自动工具将所有缩进转换为空格。
许多编辑器(例如PyCharm和SublimeText)都可以选择自动将标签转换为空格。还有一些在线工具,例如Tabs To Spaces或Browserling,可让您快速重新缩进代码。还有用Python编写的工具。例如,autopep8也可以自动重新缩进代码和其他缩进错误。
即使是最好的工具,有时也无法解决所有缩进错误,您必须手动修复它们。这就是为什么从一开始就始终正确缩进代码的重要性。
尽管不常见,但由于缩进不正确,有时会引发某些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
语句是连接的。
此类错误的修复方法是简单地正确重新缩进代码。要了解如何正确缩进代码,请参阅 如何缩进代码 部分。
答案 1 :(得分:2)
如果您使用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用户的快速修复: