提问人:Christian Dean 提问时间:8/11/2017 最后编辑:Karl KnechtelChristian Dean 更新时间:11/23/2023 访问量:78616
我收到 IndentationError(或 TabError)。我该如何解决?
I'm getting an IndentationError (or a TabError). How do I fix it?
问:
我有一个 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
这些错误意味着什么?我做错了什么?如何修复我的代码?
注意:这是对规范问题的尝试,因为我每个月都会看到许多类似的帖子。这与关于取消缩进或意外缩进的现有问题并不重复,因为它们只处理一种类型的缩进错误,我希望在一个地方涵盖它们。
逻辑上不正确的缩进也可能不会导致错误消息。一种常见的形式是附加 else
: 到 for
或 while
循环,而不是(如预期的那样)相应的 if:
。请参阅 Python while 语句上的 Else 子句,如果您需要关闭 OP 这样做的问题。
请参阅如何修复 Python 缩进,了解更多清理缩进以符合标准的工具和技术(即使它已经“有效”)。请记住,工具无法自动为您修复错误;它们只能帮助编辑,或应用不影响含义的修饰性更改。
答:
为什么缩进很重要?
在 Python 中,缩进用于分隔代码块。这与许多其他使用大括号来分隔块的语言(如 Java、Javascript 和 C)不同。正因为如此,Python 用户必须密切关注他们何时以及如何缩进代码,因为空格很重要。{}
当 Python 遇到程序缩进问题时,它会引发一个名为 IndentationError
或 TabError
的异常。也有可能从不正确的缩进中获取 SyntaxError
。
一点历史
Python 的创建者 Guido van Rossum 在一篇关于 Python 历史的文章中概述了 Python 使用缩进与可以说是更普遍接受的大括号的历史原因:{}
Python 对缩进的使用直接来自 ABC,但这个想法并非起源于 ABC——它已经由 Donald Knuth 推广,是一个众所周知的编程风格概念。(奥卡姆编程语言也使用了它。然而,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
但是,正如您可能从上面看到的那样,随机缩进您的代码非常难以阅读和遵循程序的流程。最好保持一致并遵循一种风格。
每个缩进级别使用 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 触及了这个话题:
空格是首选的缩进方法。
选项卡应仅用于与已使用选项卡缩进的代码保持一致。
但是请注意,一个很大的警告是不要同时使用制表符和空格进行缩进。这样做可能会导致各种奇怪的难以调试的缩进错误。Python 将选项卡展开到下一个第 8 列,但如果编辑器设置为 4 列的选项卡大小,或者您同时使用空格和制表符,则可以轻松生成在编辑器中看起来不错的缩进代码,但 Python 将拒绝运行。Python 3 编译器显式拒绝任何包含制表符和空格的模棱两可的程序,通常是通过引发 .但是,默认情况下,Python 2 中仍然允许混合制表符和空格,但强烈建议不要使用此“功能”。使用 和 命令行标志分别强制 Python 2 引发警告或(最好)错误。PEP8 还讨论了这个话题:TabError
-t
-tt
Python 3 不允许混合使用制表符和空格进行缩进。
混合使用制表符和空格缩进的 Python 2 代码应转换为仅使用空格。
使用 -t 选项调用 Python 2 命令行解释器时,它会发出有关非法混合制表符和空格的代码的警告。使用 -tt 时,这些警告会变成错误。强烈推荐这些选项!
“IndentationError: unexpected indent”是什么意思?
问题
当语句不必要地缩进或其缩进与同一块中先前语句的缩进不匹配时,会发生此错误。例如,下面程序中的第一个语句是不必要的缩进:
>>> 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
但是,如果您确定该行确实需要缩进,则缩进需要与同一块中前一个语句的缩进相匹配。在上面的第二个示例中使用 ,我们可以通过确保行 with 缩进与正文中的前一个语句相同的级别来修复错误: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: expected an indented block” 是什么意思?
(这也可能在 Python 3.8 或更低版本中发生。SyntaxError: unexpected EOF while parsing
问题
当 Python 看到复合语句的“标头”(例如 or)但从未定义复合语句的正文或块时,会发生此错误。例如,在下面的代码中,我们开始了一个语句,但我们从未为该语句定义正文:if <condition>:
while <condition>:
if
>>> if True:
...
File "<stdin>", line 2
^
IndentationError: expected an indented block
在第二个示例中,我们开始编写一个循环,但我们忘记缩进循环主体。因此,Python 仍然需要循环体的缩进块:for
for
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 是一个 null 操作 — 当它被执行时,什么都不会发生。当语法上需要语句但不需要执行任何代码时,它作为占位符很有用,例如:
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.
...
>>>
“IndentationError: unindent does not match any outer indentation level” 是什么意思?
问题
当您取消缩进语句时,会发生此错误,但现在该语句的缩进级别与任何以前的语句的缩进级别不匹配。例如,在下面的代码中,我们取消缩进对 的第二次调用。但是,缩进级别与任何先前语句的缩进级别都不匹配: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 引发奇怪的错误。请参阅“TabError: inconsistent use of tabs and spaces in indentation”是什么意思? 下的特殊情况小节,以更深入地解释该问题。IndentationError
“TabError: inconsistent use of tabs and spaces in indentation” 是什么意思?
问题
仅当您尝试将制表符和空格混合为缩进字符时,才会发生此错误。如上所述,Python 不允许你的程序包含制表符和空格的混合,如果它发现你有,就会引发特定的异常。例如,在下面的程序中,制表符和空格的混合用于缩进:TabError
>>> if True:
... if True:
... print()
... print()
... print()
File "<stdin>", line 5
print()
^
TabError: inconsistent use of tabs and spaces in indentation
但这通常无法直观地看到,因为许多编辑器将制表符和空格呈现相同。请注意,某些编辑器确实提供了使用不同符号呈现制表符和空间的设置,这可能会有所帮助。
对于上面的示例,这里是空格的表示形式。点是空格,箭头是制表符:
if·True:
····if·True:
→ ····print()
····print()
→ print()
我们可以看到我们确实有用于缩进的混合空格和制表符。
特殊情况
注意:如果将制表符和空格混合到程序中,Python 不会总是引发 a。如果程序缩进是明确的,Python 将允许混合使用制表符和空格。例如:TabError
>>> if True:
... if True: # tab
... pass # tab, then 4 spaces
...
>>>
有时 Python 只是扼杀了制表符和空格的混合,并在 a 更合适时错误地引发了异常。另一个例子:IndentationError
TabError
>>> if True:
... print('a') # tab
... print('b') # 4 spaces
File "<stdin>", line 3
print('b') # 4 spaces
^
IndentationError: unindent does not match any outer indentation level
正如你所看到的,以这种方式运行你的代码可能会产生神秘的错误。尽管程序在视觉上看起来很正常,但 Python 在尝试解析用于缩进的制表符和空格时变得困惑并出错。
这些都是很好的例子,演示了为什么在使用 Python 2 时永远不要混合制表符和空格并使用 and 解释器标志。-t
-tt
修复
如果您的程序很短,最简单、最快捷的解决方法可能是简单地重新缩进程序。确保每个语句在每个缩进级别缩进四个空格(请参阅如何缩进代码?)。
但是,如果您已经有一个大型程序,并且已经混合了制表符和空格,则可以使用自动化工具将所有缩进转换为空格。
许多编辑器(如 PyCharm 和 SublimeText)都有自动将制表符转换为空格的选项。还有一些在线工具,例如 Tabs To Spaces 或 Browserling,可让您快速重新缩进代码。还有一些用 Python 编写的工具。例如,AutoPEP8 可以自动重新缩进您的代码并修复其他缩进错误。
但是,即使是最好的工具有时也无法修复所有缩进错误,您必须手动修复它们。这就是为什么从一开始就始终正确缩进代码很重要的原因。
关于相关缩进问题的说明SyntaxError
有时,由于缩进不正确,会引发某些异常。例如,请看下面的代码:SyntaxError
if True:
print('x')
print('y') # oops! this statement should be indented!.
else:
print('z')
当上面的代码运行时,会引发一个:SyntaxError
Traceback (most recent call last):
File "python", line 4
else:
^
SyntaxError: invalid syntax
虽然 Python 提出了一个 ,但上述代码的真正问题是应该缩进。因为它没有缩进,所以 Python 没有意识到前面的语句和语句是要连接的。SyntaxError
print('y')
if
else
此类错误的解决方法是简单地正确地重新缩进代码。若要了解如何正确缩进代码,请参阅如何缩进代码?部分。
我仍然很难使用 Python 的缩进语法。我该怎么办?
如果您仍在挣扎,请不要气馁。可能需要一些时间来适应 Python 的空格语法规则。以下是一些帮助提示:
- 获取一个编辑器,该编辑器会在出现缩进错误时告诉您。如上所述,一些商品是 PyCharm、SublimeText 和 Jupyter Notebook。
- 缩进代码时,大声数自己按空格键(或 Tab 键)的次数。例如,如果您需要将一行缩进四个空格,您可以大声说出“一、二、三、四”,同时每次按下空格键。这听起来很傻,但它有助于训练你的大脑思考你缩进代码的深度。
- 如果您有编辑器,请查看它是否具有自动将制表符转换为空格的选项。
- 查看其他人的代码。浏览 GitHub 或 Stack Overflow 并查看 Python 代码示例。
- 只需编写代码即可。这是变得更好的唯一最佳方法。你写的 Python 代码越多,你就会越好。
使用的资源
- 维基百科上的数据
- Python 3 文档
- Guido van Rossum 的 Python 历史
- PEP 8
评论
def
TabError
TabError
你看,你有一个小错误。
if True:
if False:
print('foo')
print('bar')
你应该做:
if True:
if False:
print('foo')
print('bar')
正如你所看到的,你的打印只有缩进三个空格,但它需要缩进四个空格才能与上一个缩进在同一级别(语句)对齐。if
评论
Sublime Text 用户的快速修复:
- 按 + 访问查找和替换CtrlH
- 在“查找”中:键入四个空格
- 在“替换”中:从代码中的某个位置复制并粘贴选项卡。 单击“全部替换”
评论
“查看→缩进”→“将缩进转换为空间
”菜单选项。\t
崇高的文字 3
如果您碰巧在 Sublime Text 3 中编码,这可以帮助您解决缩进问题。
在 Sublime Text 中,在编辑 Python 文件时:
Sublime, 菜单 文本 → 首选项 → 设置 - 特定语法:
文件 Python.sublime-settings
{
"tab_size": 4,
"translate_tabs_to_spaces": true
}
Python 2 的历史注释
默认情况下,Python 2 允许混合使用制表符和空格,默认情况下不会产生错误。将该选项传递给 Python 2.x 会导致它在与 3.x 相同的情况下引发异常,并导致警告。完整的细节在 Python 对缩进的制表符和空格的解释中进行了解释。-tt
-t
特别要注意的是,制表符被视为 8 个空格(相反,它们有效地将感知空格的数量增加到 8 的下一个倍数)。因此,如果使用标准的 4 空格缩进显示代码,但混合了空格和制表符,则最终可能会得到满足缩进规则的代码,但不会被视为缩进方式与外观相同。
因此,您可能会遇到各种其他错误。例如:
# in 2.x
def example():
def nested(): # suppose this is indented with a tab
x = [1] # and this with two tabs
print x[0] + 1 # but this with 8 spaces instead of a tab
nested()
(请注意,即使我使用制表符,Stack Overflow 的 Markdown 渲染也会将缩进显示为空格。
这给出了一个 ,因为 不再在函数内部,并且在外部 中超出了范围。类似地,我们可以通过给一个 local 来轻松地创建一个 local ,或者给它一个 local .NameError
print x
nested
x
example
TypeError
example
x = 1
ValueError
x = []
快速清单
- 不正确的缩进通常会导致 ,但也可能导致 (的子类型 ) 或 (缩进本身是合法的,但它会导致其他代码出现语法错误)。缩进对 Python 代码有效,但对程序员的意图是错误的,会导致逻辑错误(代码不会引发异常,但会做错一些事情)。
IndentationError
TabError
IndentationError
SyntaxError
- 强烈建议不要使用制表符进行缩进。在 2.x 中,使用命令行参数运行 Python 会导致它引发相同的问题,这对于查找问题很有用。
-tt
TabError
- PEP 8 中规定的社区标准是每个缩进级别使用四个空格。
- 像 、 、 、 等 这样以冒号结尾的语句后面需要一个缩进块:
if
for
while
def
class
:
if x: do_y() # <- this must be indented
- 块不能为空,注释不算作使块“不为空”。如果什么都不应发生,请使用
pass
语句:if x: pass # this statement does nothing, except make the block non-empty
- 块中的代码必须具有相同的缩进:
if x: do_y() do_z() # this needs to line up with do_y()
- 占用整行的注释在标记之前可能有任意数量的空格。
#
- 文档字符串不是注释,必须以与以下代码相同的方式缩进。
- 与开始语句或较低级别的缩进对齐的第一行代码位于块外部:
if x: do_y() do_z() # this happens regardless of the x value # cannot write `else`: here; that is a syntax error for i in range(10): if x: do_y() do_z() # both the `if` and `for` blocks are ended
- Python 将选项卡解释为扩展到下一个第 8 列;但在 3.x 中,混合空格和制表符的缩进必须具有完全相同的模式才能算作相同的缩进(并且进一步缩进需要具有与前缀相同的模式)。如果做不到这一点,将导致 .
TabError
while
Python 中的循环可能有一个else
子句,如果循环正常完成而不是通过break
完成,则执行该子句。这是逻辑错误的常见来源:for
for i in range(10): if i % 2: print(f'{i} is odd') else: # wrongly indented print(f'{i} is even') # only happens once, and claims 9 is even!
下一个:错误:找不到函数...在 R 中
评论