为什么缩进很重要?
在 Python 中,缩进用于分隔blocks of code。这与许多其他使用花括号 {} 来分隔块的语言(如 Java、Javascript 和 C)不同。因此,Python 用户必须密切注意何时以及如何缩进代码,因为空格很重要。
当 Python 遇到程序缩进问题时,它会引发名为 IndentationError 或 TabError 的异常。
一点历史
an article of the history of Python by Guido van Rossum 概述了 Python 使用缩进与可以说更普遍接受的花括号 {} 的历史原因 - 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
但是,正如您可能从上面所说的那样,随机缩进您的代码非常难以阅读和遵循程序的流程。最好保持一致并遵循一种风格。
PEP 8 -- the Python style guide -- says:
每个缩进级别使用 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 中仍然允许混合制表符和空格,但强烈建议不要使用此“功能”。使用 -t 和 -tt 命令行标志来强制 Python 2 分别发出警告或(最好)错误。 PEP8 also discusses this topic:
Python 3 不允许在缩进中混合使用制表符和空格。
混合使用制表符和空格缩进的 Python 2 代码应转换为仅使用空格。
当使用 -t 选项调用 Python 2 命令行解释器时,它会发出有关非法混合制表符和空格的代码的警告。使用 -tt 时,这些警告会变成错误。强烈推荐这些选项!
“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: expected an indented block”是什么意思?
问题
当 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 期望一个或多个语句作为占位符的任何地方使用。 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)
这是上面的示例,其中使用 pass 关键字修复了 if 语句:
>>> if True:
... pass # We don't want to define a body.
...
>>>
“IndentationError: unindent does not match any external indentation level”是什么意思?
问题
当您取消缩进一个语句时会发生此错误,但现在该语句的缩进级别与任何先前语句的缩进级别不匹配。例如,在下面的代码中,我们取消了对print 的第二次调用。但是,缩进级别与之前的任何语句都不匹配:
>>> if True:
... if True:
... print('yes')
... print()
File "<stdin>", line 4
print()
^
IndentationError: unindent does not match any outer indentation level
这个错误特别难捕捉,因为即使是一个空格也会导致你的代码失败。
修复
解决方法是确保当您取消缩进语句时,缩进级别与前一个语句的缩进级别相匹配。再次考虑上面的例子。在示例中,我希望第二个 print 调用位于第一个 if 语句正文中。所以我需要确保该行的缩进级别与第一个 if 语句正文中的前一个语句的缩进级别相匹配:
>>> if True:
... if True:
... print('yes')
... print() # indentation level now matches former statement's level.
...
yes
>>>
我仍然收到 IndentationError 但我的程序似乎正确缩进。我该怎么办?
如果您的程序在视觉上看起来有正确的缩进,但您仍然得到IndentationError,那么您很可能混合了带有空格的制表符。这有时会导致 Python 引发奇怪的错误。请参阅“TabError:缩进中制表符和空格的不一致使用”下的特殊情况小节是什么意思?更深入地解释问题。
“TabError:缩进中制表符和空格的使用不一致”是什么意思?
问题
仅当您尝试将制表符和空格混合为缩进字符时,才会出现此错误。如上所述,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
如您所见,以这种方式运行代码会产生神秘的错误。尽管程序视觉上看起来不错,但 Python 在尝试解析用于缩进的制表符和空格时感到困惑并出错。
这些很好的例子说明了为什么在使用 Python 2 时不要混合制表符和空格,并使用 -t 和 -tt 解释器标志。
修复
如果您的程序很短,最简单和最快的解决方法可能是简单地重新缩进程序。确保每个语句在每个缩进级别缩进四个空格(请参阅如何缩进我的代码?)。
但是,如果您已经有一个混合了制表符和空格的大型程序,则可以使用自动化工具将所有缩进转换为空格。
PyCharm 和SublimeText 等许多编辑器都具有自动将制表符转换为空格的选项。还有一些在线工具,例如Tabs To Spaces 或Browserling,可让您快速重新缩进代码。还有一些用 Python 编写的工具。例如,autopep8 可以自动重新缩进您的代码并修复其他缩进错误。
即使是最好的工具有时也无法修复所有缩进错误,您必须手动修复它们。这就是为什么从一开始就正确缩进代码很重要。
关于“SyntaxError”相关缩进问题的说明
虽然不经常,但有时由于不正确的缩进会引发某些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 的空格语法规则。以下是一些帮助提示:
- 获取一个编辑器,它会在您遇到缩进错误时告诉您。部分商品如上所说,PyCharm、SublimeText、Jupyter Notebook。
- 当您缩进代码时,大声数自己按空格键(或 Tab 键)的次数。例如,如果您需要将一行缩进四个空格,您会大声说“one, two, three, 四个”,同时每次同时按下空格键。这听起来很傻,但它有助于训练你的大脑思考你的代码缩进有多深。
- 如果您有编辑器,请查看它是否具有自动将制表符转换为空格的选项。
- 查看其他人的代码。浏览 github 或 Stackoverflow 并查看 Python 代码示例。
- 只需编写代码。这是变得更好的唯一最佳方法。你写的 Python 代码越多,你就会越好。
使用的资源