Подтвердить что ты не робот

Я получаю 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

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

4b9b3361

Ответ 1

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

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

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

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

Исторические причины, по которым 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

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

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 -tt предупреждение или (предпочтительно) ошибку соответственно. PEP8 также обсуждает эту тему:

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

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

При вызове интерпретатора командной строки Python 2 с опцией -t он выдает предупреждения о коде, который незаконно смешивает табуляции и пробелы. При использовании -t t эти предупреждения становятся ошибками. Эти варианты настоятельно рекомендуются!

Что означает "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 тела цикла for. Таким образом, Python все еще ожидает блок с отступом 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 можно использовать везде, где 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

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

исправлять

Исправление состоит в том, чтобы гарантировать, что при отмене отступа в операторе уровень отступа совпадает с уровнем предыдущего оператора. Рассмотрим приведенный выше пример еще раз. В этом примере я хочу, чтобы второй вызов print был в первом теле оператора if. Поэтому мне нужно убедиться, что уровень отступа строки соответствует уровню предыдущих операторов в первом теле оператора if:

>>> if True:
...     if True:
...         print('yes')
...     print() # indentation level now matches former statement 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, имеют опции для автоматического преобразования вкладок в пробелы. Есть также несколько онлайн-инструментов, таких как Tabs To Spaces или Browserling, которые позволяют быстро переопределить ваш код. Есть также инструменты, написанные на Python. Например, autopep8 может автоматически переопределить ваш код и другие ошибки отступа.

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

Замечание о проблемах с отступами в SyntaxError

Хотя и не часто, иногда 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.
  • Когда вы делаете отступ в своем коде, подсчитайте себе, сколько раз вы нажимаете клавишу пробела (или клавишу табуляции). Например, если вам нужно сделать отступ на четыре пробела, вы должны произнести вслух "один, два, три, четыре", одновременно нажимая клавишу пробела. Звучит глупо, но это помогает тренировать ваш мозг думать о том, как глубоко вы делаете отступ в своем коде.
  • Если у вас есть редактор, посмотрите, есть ли у него опция автоматического преобразования вкладок в пробелы.
  • Посмотреть чужой код. Просмотрите github или /fooobar.com/... и посмотрите примеры кода Python.
  • Просто напишите код. Это единственный лучший способ стать лучше. Чем больше вы пишете код Python, тем лучше вы получите.

Используемые ресурсы

Ответ 2

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

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

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

Меню Sublime Text > Настройки > Настройки - Синтаксис:

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

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

Ответ 3

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

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

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

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

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

Ответ 4

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

  1. Нажмите Ctrl-H, чтобы получить доступ к поиску и замене
  2. В Find: введите 4 пробела
  3. In Replace: скопируйте и вставьте вкладку из своего кода. Нажмите Replace All.