Я получаю IndentationError. Как это исправить?

у меня есть 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

что означают эти ошибки? Что я делаю не так? Как я могу исправить свой код?

4 ответов


почему отступ имеет значение?

в Python отступ используется для разграничения блоки кода. Это отличается от многих других языков, которые используют фигурные скобки {} для разграничения блоков, таких как Java, Javascript и C. Из-за этого пользователи Python должны уделять пристальное внимание тому, когда и как они отступают от своего кода, потому что имеет значение пробел.

когда Python сталкивается с проблемой с отступом вашей программы, он либо вызывает исключение называется IndentationError или TabError.

немного истории

исторические причины того, почему Python использует отступы против, возможно, более общепринятых фигурных скобок {} изложена в статья из истории Python Гвидо ван Россума - создатель Python:

использование отступов Python происходит непосредственно из ABC, но эта идея не возникла с ABC-он уже был продвинут Дональдом Кнутом и был хорошо известной концепцией стиля программирования. (Язык программирования occam также использовал его.) Однако авторы ABC изобрели использование двоеточия, которое отделяет предложение о вводе от отступа блока. После раннего тестирования пользователя без двоеточия было обнаружено, что смысл отступа был неясен новичкам, обучаемым первым шагам программирования. Добавление толстой кишки значительно прояснило его: толстая кишка каким-то образом привлекает внимание к тому, что следует, и связывает фразы До и после него вместе в правильном направлении.

как сделать отступ мой код?

основное правило для отступа кода 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-руководство по стилю Python-рекомендует четыре пробела на уровень отступа следует использовать:

используйте 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 явно отклоняет любую программу, содержащую неоднозначную смесь вкладок и пробелов, обычно поднимая TabError. Однако, по умолчанию, смешивание вкладок и пробелов все еще разрешено в Python 2, но настоятельно рекомендуется не использовать эту "функцию". Используйте -t и -tt флаги командной строки, чтобы заставить Python 2 поднять предупреждение или (предпочтительно) ошибку соответственно. PEP8 также обсуждает эту тему:

Python 3 запрещает смешивание вкладок и пробелов для отступов.

код Python 2 с отступом со смесью вкладок и пробелов должен быть преобразован в использование исключительно пробелов.

при вызове интерпретатора командной строки Python 2 с параметром-t он выдает предупреждения о коде, который незаконно смешивает вкладки и пробелы. При использовании-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 может быть исправлено просто быть unindenting линии:

>>> 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 оператор можно использовать. The pass оператор может использоваться везде, где Python ожидает один или несколько операторов в качестве заполнителя. из документации 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 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

здесь изображение, которое визуально показывает пробелы в вышеуказанной программе. Серые точки-это пробелы, а серые стрелки-вкладки:

enter image description here

мы действительно смешанные пробелы и знаки табуляции для отступов.

особых случаях

Обратите Внимание На 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 запутался, пытаясь разобрать вкладки и пробелы, используемые для отступов и ошибок.

это отличные примеры, которые демонстрируют, почему никогда не смешивайте пробелы и символы табуляции и использовать -t и -tt флаги интерпретатора при использовании Python 2.

исправить

если ваша программа короткая, вероятно, самым простым и быстрым решением является просто повторный отступ программы. Убедитесь, что каждый оператор отступается четырьмя пробелами на уровень отступа (см. как я отступ мой код?).

однако, если у вас уже есть большая программа, в которую вы смешали вкладки и пробелы, есть автоматические инструменты, которые можно использовать для преобразования всех ваших отступов в просто пробелы.

многие редакторы, такие как PyCharm и SublimeText есть опции для автоматического преобразования вкладок в пробелы. Есть также несколько он-лайн инструментов, таких как Вкладки В Пробелы или Browserling это позволяет быстро изменить отступ кода. Есть также инструменты, написанные на Python. autopep8 например, может автоматически повторно отступать ваш код и другие ошибки отступа, а также.

даже лучшие инструменты, хотя иногда не смогут исправить все ваши ошибки отступов, и вам придется исправить их вручную. Вот почему важно всегда правильно отступать от кода с самого начала.

записку о "SyntaxError" связанные проблемы отступа

хотя и не часто, иногда некоторые SyntaxError исключения возникают из-за неправильного отступа. Например, посмотрите на код ниже:

if True:
    pass
pass # oops! this statement should be indented!.
else:
    pass

при выполнении вышеуказанного кода a SyntaxError is raised:

Traceback (most recent call last):
  File "python", line 4
    else:
       ^
SyntaxError: invalid syntax

хотя Python поднимает SyntaxError, the реальные проблема с вышеуказанным кодом, это второй pass заявление должно быть с отступом. Потому что второй pass не изрезаны, Python не понимает, что предыдущий if заявления и else оператор предназначен для подключения.

исправить этот тип ошибки-просто правильно изменить отступ вашего кода. Чтобы узнать, как правильно отступить код, см. раздел как сделать отступ мой код?.

мне все еще трудно с синтаксисом отступов Python. Что мне делать?

не расстраивайтесь, если вы все еще боретесь. Он может потребоваться время, чтобы привыкнуть к Правила синтаксиса пробелов Python. Вот несколько советов, которые помогут:

  • получите редактор, который сообщит вам, когда у вас есть ошибка отступа. Некоторые товары, как сказано выше,PyCharm, SublimeText и Jupyter Notebook.
  • когда вы отступаете свой код, подсчитайте вслух для себя, сколько раз вы нажимаете пробел (или клавишу tab). Например, если вам нужно, чтобы отступ строчка на четыре пробела, вы бы сказали вслух"один, два, три, четыре " при одновременном нажатии пробела каждый раз. Это звучит глупо, но это помогает тренировать ваш мозг, чтобы думать о том, как глубоко вы отступаете свой код.
  • если у вас есть редактор, посмотрите, есть ли у него возможность автоматически конвертировать вкладки в пробелы.
  • Просмотр кода других. Обзор github или Stackoverflow и см. примеры кода Python.
  • просто писать код. Это единственный лучший способ стать лучше. Чем больше вы пишете код Python, тем лучше вы получите.

ресурсы используется


Возвышенный Текст 3

если случится, что вы кодируете в Sublime Text 3, это может помочь вам с отступами problemes

в Sublime Text при редактировании файла Python:

возвышенное текстовое меню>предпочтения>Настройки Используется Специальный Синтаксис :

Python.sublime-настройки

{
    "tab_size": 4,
    "translate_tabs_to_spaces": true
}

вы видите, у вас есть небольшая ошибка.

if True:
    if False:
        print('foo')
   print('bar')

вы должны были делать:

if True:
    if False:
        print('foo')
    print('bar')

Как вы можете видеть, ваша печать имеет только отступ 3 пробела, она должна быть отступом 4 пробела.


быстрое исправление для пользователей Sublime:

  1. нажмите Ctrl-H для доступа к Find и Replace
  2. в Find: введите 4 пробела
  3. in Replace: скопируйте и вставьте вкладку откуда-нибудь из вашего кода Нажмите Кнопку Заменить Все