我收到一个IndentationError。我如何解决它? - python

我有一个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

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

python大神给出的解决方案

缩进为何重要?
在Python中,缩进用于定界blocks of code。这与许多其他使用大括号{}来分隔块(例如Java,Javascript和C)的语言不同。因此,Python用户必须密切注意缩进代码的时间和方式,因为空格很重要。
当Python遇到程序缩进问题时,它会引发称为IndentationErrorTabError的异常。
一点历史
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仍允许混合使用制表符和空格,但是强烈建议不要使用此“功能”。使用-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

在此示例中,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.
... 

“ 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希望将一个或多个语句用作占位符的任何地方使用。 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.
... 
>>>

“ IndentationError: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将不允许您的程序包含制表符和空格的混合,并且如果发现您有该异常,将引发特定异常TabError。例如,在下面的程序中,制表符和空格的混合用于缩进:

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

这是一张图片,直观地显示了上述程序中的空白。灰色点是空格,灰色箭头是标签:
我收到一个IndentationError。我如何解决它? - python
我们可以看到我们确实有混合的空格和缩进制表符。
特别案例
注意如果将制表符和空格混入程序中,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键)的次数。例如,如果您需要将一行缩进四个空格,您会大声说“一,二,三,四”,同时每次按下空格键。听起来很傻,但是它可以帮助您训练大脑思考代码缩进的深度。
如果您有编辑器,请查看它是否具有将制表符自动转换为空格的选项。
查看其他人的代码。浏览github或Stackoverflow并查看Python代码示例。
只需编写代码。那是变得更好的唯一最佳方法。您编写Python代码的次数越多,您将获得越多的收益。

使用资源

https://en.wikipedia.org/
https://docs.python.org/3/
http://python-history.blogspot.com/2009/02/early-language-design-and-development.html
https://www.python.org/dev/peps/pep-0008/

Spacy如何将标记标签整体化? - python

在包含#标签(例如tweet)的句子中,spacy的令牌生成器将标签分为两个令牌:import spacy nlp = spacy.load('en') doc = nlp(u'This is a #sentence.') [t for t in doc] 输出:[This, is, a, #, sentence, .…

如何在Matplotlib条形图后面绘制网格线 - python

x = ['01-02', '02-02', '03-02', '04-02', '05-02'] y = [2, 2, 3, 7, 2] fig, ax = plt.subplots(1, 1) ax.bar(range(len(y)), y, width=…

对于DataFrame的每一行,在给定条件的情况下获取第一列的索引到新列中 - python

这是我的数据框的一部分。data = [ ['1245', np.nan, np.nan, 1.0, 1.0, ''], ['1246', np.nan, 1.0, 1.0, 1.0, ''], ['1247', 1.0, 1.0, 1.0, 1.0, �…

在Flask中测试文件上传 - python

我在Flask集成测试中使用Flask-Testing。我有一个表单,该表单具有我要为其编写测试的徽标的文件上传,但是我不断收到错误消息:TypeError: 'str' does not support the buffer interface。我正在使用Python3。我找到的最接近的答案是this,但是它对我不起作用。这是我的许多尝…

搜索csv文件,最佳实践是什么? - python

我有一个看起来像这样的CSV文件:(在我的CSV文件中没有标题,但为清楚起见,我在此处添加了标题)geneName, personNumber, allele1, allele2 gene-1-A, PERSON1, C, G gene-2_s, PERSON1, A, C gene_3_D, PERSON1, T, T . . . gene-1_A, PE…