Я получаю ошибку отступа (или TabError). Как мне это исправить?
У меня есть скрипт на 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
Что означают эти ошибки? Что я делаю не так? Как я могу исправить свой код?
Это канонический вопрос, предназначенный для рассмотрения обычных причин IndentationError
в том же месте, потому что концептуальная проблема - знание того, как делать отступ и почему / где - одна и та же.
Есть несколько установленных канонических вопросов для определенных, более конкретных случаев, когда концептуальная проблема заключается не в отступе как таковом:
* Смотрите Как написать пустой блок с отступом в Python? для случаев, когда все выстроено так, как должно быть, за исключением того, что в другом месте был намеренно пустой блок с отступом, обнаруженный как неправильный.
* Смотрите Почему я получаю IndentationError от функции с правильным отступом (после "try" без "except")? для случаев, вызванных отсутствием блока except
или finally
. Обратите внимание, что последние версии Python сообщают об ошибке более четко, но более старые вводят в заблуждение проблему как неправильный отступ в последующем коде.
* Копируйте-вставляйте в интерактивный интерпретатор Python и делайте отступы на самом деле речь идет не о правильном выборе отступа, а о том, что происходит при вставке кода в REPL Python (потому что он ожидает ввода одного блока за раз вручную). Однако обычно это приводит к появлению сообщения IndentationError
.
Также возможно иметь логически неправильный отступ, который не вызывает сообщение об ошибке. Одной из распространенных форм этого является присоединение else:
к циклу for
or while
вместо (как предполагалось) соответствующего if:
. Смотрите Предложение Else в операторе Python while
Смотрите Как исправить отступ в Python, чтобы узнать больше инструментов и приемов для приведения отступов в соответствие со стандартами (даже если это уже "работает"). Имейте в виду, что инструменты не могут автоматически исправлять ошибки за вас; они могут только помочь с редактированием или внести косметические изменения, которые не влияют на смысл.
Переведено автоматически
Ответ 1
Почему отступ имеет значение?
В Python отступ используется для разделения блоков кода. Это отличается от многих других языков, которые используют фигурные скобки {}
для разделения блоков, таких как Java, Javascript и C. Из-за этого пользователи Python должны уделять пристальное внимание тому, когда и как они делают отступы в своем коде, потому что пробелы имеют значение.
Когда Python сталкивается с проблемой с отступом в вашей программе, это либо вызывает исключение с именем IndentationError
или TabError
. Также возможно получить SyntaxError
из-за неправильного отступа.
Немного истории
Исторические причины, по которым Python использует отступ по сравнению с, возможно, более общепринятыми фигурными скобками, {}
изложены в статье "История Python " Гвидо ван Россума - создателя Python:
Использование отступов в Python происходит непосредственно из ABC, но эта идея возникла не из ABC - она уже была продвинута Дональдом Кнутом и была хорошо известной концепцией стиля программирования. (Язык программирования 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 - руководство по стилю 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
можно исправить, просто сняв отступ со строки:
>>> 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: ожидается блок с отступом"?
(Это также может происходить, как SyntaxError: unexpected EOF while parsing
в Python 3.8 или ниже.)
Проблема
Эта ошибка возникает, когда Python видит "заголовок" для составного оператора, такого как if <condition>:
or 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 — это нулевая операция - при ее выполнении ничего не происходит. Он полезен в качестве заполнителя, когда оператор требуется синтаксически, но код не требуется выполнять, например:
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
Эту ошибку особенно трудно отловить, потому что даже один пробел приведет к сбою вашего кода.
Исправить
Исправление заключается в том, чтобы гарантировать, что при снятии отступа с оператора уровень отступа соответствовал уровню предыдущего оператора. Рассмотрим приведенный выше пример еще раз. В примере я хочу, чтобы второй вызов print был в теле первого if
оператора. Итак, мне нужно убедиться, что уровень отступа этой строки соответствует уровню отступа предыдущих операторов в теле первого if
оператора:
>>> if True:
... if True:
... print('yes')
... print() # indentation level now matches former statement's level.
...
yes
>>>
Я по-прежнему получаю ошибку отступа, но моя программа, похоже, имеет правильный отступ. Что мне делать?
Если визуально кажется, что ваша программа имеет правильный отступ, но вы по-прежнему получаете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
Но это часто невозможно увидеть визуально, поскольку многие редакторы отображают табуляции и пробелы одинаково. Обратите внимание, что некоторые редакторы предлагают настройки для отображения табуляций и пробелов разными символами, что может быть полезно.
Для приведенного выше примера вот представление пробела. Точки - это пробелы, а стрелки - символы табуляции:
if·True:
····if·True:
→ ····print()
····print()
→ print()
Мы видим, что у нас действительно смешаны пробелы и табуляции для отступов.
Особые случаи
Примечание Python не всегда выдает a TabError
, если вы смешиваете табуляции и пробелы в своей программе. Если отступ в программе однозначный, Python разрешит смешивать табуляцию и пробелы. Например:
>>> if True:
... if True: # tab
... pass # tab, then 4 spaces
...
>>>
И иногда Python просто захлебывается смесью табуляции и пробелов и ошибочно создает 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 запутался, пытаясь разобрать табуляции и пробелы, используемые для отступов, и выдал ошибку.
Это отличные примеры, демонстрирующие, почему никогда не следует смешивать табуляцию и пробелы и использовать флаги интерпретатора -t
и -tt
при использовании Python 2.
Исправить
Если ваша программа короткая, вероятно, самое простое и быстрое решение - просто изменить отступ в программе. Убедитесь, что каждая инструкция имеет отступ на четыре пробела для каждого уровня отступа (см. Как мне сделать отступ в моем коде?).
Однако, если у вас уже есть большая программа, в которой вы смешали табуляцию и пробелы, существуют автоматизированные инструменты, которые можно использовать для преобразования всего вашего отступа только в пробелы.
Многие редакторы, такие как PyCharm и SublimeText, имеют опции автоматического преобразования табуляции в пробелы. Также существует несколько онлайновых инструментов, таких как табуляция в пробелы или браузерлинг, которые позволяют быстро изменять отступы в вашем коде. Также существуют инструменты, написанные на 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 выдает SyntaxError
, реальная проблема с приведенным выше кодом заключается в том, что print('y')
должен быть отступ. Поскольку в нем нет отступов, Python не понимает, что предыдущий if
оператор и else
оператор должны быть связаны.
Исправление ошибки этого типа заключается в том, чтобы просто правильно изменить отступ в вашем коде. Чтобы узнать, как правильно сделать отступ в вашем коде, смотрите Раздел Как мне сделать отступ в моем коде?.
У меня все еще проблемы с синтаксисом отступов Python. Что мне делать?
Не отчаивайтесь, если у вас все еще проблемы. Может потребоваться время, чтобы привыкнуть к правилам синтаксиса пробелов Python. Вот несколько советов, которые помогут:
- Получите редактор, который сообщит вам, когда у вас возникнет ошибка отступа. Некоторые из них, как указано выше, являются, PyCharm, SublimeText и Jupyter Notebook.
- Когда вы делаете отступ в своем коде, сосчитайте вслух про себя, сколько раз вы нажимаете пробел (или клавишу табуляции). Например, если вам нужно сделать отступ в строке на четыре пробела, вы должны произнести вслух "один, два, три, четыре", каждый раз одновременно нажимая клавишу пробела. Звучит глупо, но это помогает приучить ваш мозг думать о том, насколько глубокий отступ вы делаете в своем коде.
- Если у вас есть редактор, посмотрите, есть ли в нем опция автоматического преобразования табуляции в пробелы.
- Просмотрите чужой код. Просмотрите GitHub или Stack Overflow и посмотрите примеры кода Python.
- Просто напишите код. Это единственный лучший способ стать лучше. Чем больше вы пишете кода на Python, тем лучше у вас получается.
Используемые ресурсы
- Википедия
- Документация по Python 3
- История Python, Гвидо ван Россум
- PEP 8
Ответ 2
Sublime Text 3
Если случается, что вы кодируете в Sublime Text 3, это может помочь вам с проблемами отступов.
В Sublime Text при редактировании файла Python:
Sublime, меню Текст → Настройки → Синтаксис зависит:
Файл Python.sublime-настройки
{
"tab_size": 4,
"translate_tabs_to_spaces": true
}
Ответ 3
Краткий контрольный список
- Неправильный отступ чаще всего приводит к
IndentationError
, но это также может привести кTabError
(подтипIndentationError
) илиSyntaxError
(сам отступ был допустимым, но это привело к синтаксической ошибке в другом коде). Отступ, который допустим для кода Python, но не соответствует намерениям программиста, вызывает логические ошибки (код не создает исключение, но делает что-то неправильно). - Настоятельно рекомендуется не использовать табуляцию для отступа. В 2.x запуск Python с
-tt
аргументом командной строки приводит к тому, что он выдает то же самоеTabError
, что полезно для поиска проблем. - Стандарт сообщества, изложенный в PEP 8, заключается в использовании четырех пробелов для каждого уровня отступа.
- Такие операторы, как
if
,for
,while
,def
class
, и:
etc, которые заканчиваются двоеточием, требуют, чтобы после них стоял блок с отступом, и после них: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
иfor
циклы в Python могут содержать предложениеelse
, которое выполняется, если цикл завершается нормально, а не черезbreak
. Это распространенный источник логических ошибок: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!
Ответ 4
Историческая справка для Python 2
По умолчанию Python 2 допускает смешивание табуляции и пробелов и по умолчанию не выдает ошибку. Передача -tt
опции в Python 2.x вызывает исключение в тех же случаях, что и 3.x, и -t
вместо этого вызывает предупреждение. Полная информация объясняется в интерпретации табуляций и пробелов в Python для отступа.
Обратите особое внимание, что табуляции обрабатываются как 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()
(Обратите внимание, что рендеринг Markdown в Stack Overflow покажет отступ в виде пробелов, даже если я использую табуляцию.)
Это дает NameError
, поскольку print x
больше не находится внутри nested
функции и x
находится вне области видимости во внешней example
. Аналогично, мы могли бы легко создать a, TypeError
указав example
local x = 1
или ValueError
присвоив ему local x = []
.