web-dev-qa-db-ja.com

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

私は自分のプログラムで遊んでいましたが、他にも3つのエラーを生成することができました。

  • IndentationError: unexpected indent
  • IndentationError: expected an indented block
  • TabError: inconsistent use of tabs and spaces in indentation

これらのエラーはどういう意味ですか?私は何を間違えていますか?コードを修正するにはどうすればよいですか?

38
Christian Dean

インデントが重要なのはなぜですか?

Pythonでは、インデントは コードブロック を区切るために使用されます。これは、中括弧{}を使用してJava、Javascript、Cなどのブロックを区切る他の多くの言語とは異なります。このため、Pythonユーザーは、インデントするタイミングと方法に細心の注意を払う必要があります空白が重要だからです。

Pythonがプログラムのインデントに問題を検出すると、 IndentationError または TabError と呼ばれる例外が発生します。

少しの履歴

Pythonがインデントを使用する理由と、ほぼ間違いなく一般的に受け入れられている中括弧{}の歴史的な理由は、 Guido vanによるPythonの歴史に関する記事Rossum -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つのスペースを使用することを推奨 を使用する必要があります。

インデントレベルごとに4つのスペースを使用します。

つまり、新しいブロックを開始する各ステートメントと、新しいブロック内の後続の各ステートメントは、現在のインデントレベルから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はこのトピックについて触れています

推奨されるインデント方法はスペースです。

タブは、すでにタブでインデントされているコードとの一貫性を保つためにのみ使用する必要があります。

ただし、1つの大きな注意点は、両方のタブを使用しないことです。andインデント用のスペース。これを行うと、インデントエラーをデバッグするのが難しくなります。 Pythonはタブを次の8列目に展開しますが、エディターが4列のタブサイズに設定されている場合、またはスペースとタブを使用する場合、looksエディターでは問題ありませんが、Pythonは実行を拒否します。 Python 3コンパイラexplicitlyは、通常TabErrorを上げることにより、タブとスペースのあいまいな混合を含むプログラムを拒否します。ただし、デフォルトでは、Python 2ではタブとスペースの混在が引き続き許可されていますが、この「機能」を使用しないことを強くお勧めします。 -tおよび-ttコマンドラインフラグを使用して、それぞれPython 2に警告または(できれば)エラーを強制的に発生させます。 PEP8はこのトピックについても説明しています

Python 3は、インデントにタブとスペースを使用することを許可していません。

タブとスペースが混在してインデントされたPython 2コードは、スペースのみを使用するように変換する必要があります。

-tオプションを指定してPython 2コマンドラインインタープリターを呼び出すと、タブとスペースが不正に混在するコードに関する警告が発行されます。 -ttを使用すると、これらの警告はエラーになります。これらのオプションを強くお勧めします!

「IndentationError:unexpected indent」はどういう意味ですか?

問題

このエラーは、ステートメントが不必要にインデントされるか、そのインデントが同じブロック内の以前のステートメントのインデントと一致しない場合に発生します。たとえば、次のプログラムの最初のステートメントは不必要にインデントされています。

>>>  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を使用する2番目の例では、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 a indented block」とはどういう意味ですか?

問題

このエラーは、Pythonがif <condition>:while <condition>:などの複合ステートメントの「ヘッダー」を見たときに、複合ステートメントの本体またはblockは定義されません。たとえば、次のコードではifステートメントを開始しましたが、ステートメントの本体を定義することはありません。

>>> if True:
... 
  File "<stdin>", line 2

    ^
IndentationError: expected an indented block

この2番目の例では、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がプレースホルダーとして1つ以上のステートメントを想定している場所であればどこでも使用できます。 passのドキュメントから

passはnull操作です。実行されても何も起こりません。ステートメントが構文的に必要であるが、コードを実行する必要がない場合、プレースホルダーとして役立ちます。次に例を示します。

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の2番目の呼び出しのインデントを解除します。ただし、インデントレベルは以前のステートメントのレベルと一致しません。

>>> if True:
...     if True:
...         print('yes')
...    print()
  File "<stdin>", line 4
    print()
          ^
IndentationError: unindent does not match any outer indentation level

このエラーは、スペースを1つでも使用するとコードが失敗するため、キャッチするのが特に困難です。

修正

修正方法は、ステートメントのインデントを解除するときに、インデントレベルが前のステートメントのインデントレベルと一致するようにすることです。上記の例をもう一度考えてみましょう。例では、最初のifステートメントの本文に印刷する2番目の呼び出しが必要です。したがって、その行のインデントレベルが、最初のifステートメントの本文の前のステートメントのインデントレベルと一致することを確認する必要があります。

>>> if True:
...     if True:
...         print('yes')
...     print() # indentation level now matches former statement's level.
... 
yes

>>> 

私はまだIndentationErrorを受け取っていますが、私のプログラムは正しくインデントされているようです。私は何をしますか?

プログラムに正しいインデントがあるように見えても、IndentationErrorを取得している場合は、タブにスペースが混在している可能性があります。これにより、Pythonが奇妙なエラーを引き起こすことがあります。 特別な場合のサブセクションWhat's "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 will notalwaysプログラムにタブとスペースを混在させる場合は、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

ご覧のとおり、この方法でコードを実行すると、ミステリアスなエラーが発生する可能性があります。プログラムvisuallyは問題ないように見えますが、Pythonはインデントに使用されるタブとスペースを解析しようとして混乱し、エラーになりました。

これらは、タブとスペースを混在させず、Python 2を使用するときに-tおよび-ttインタープリターフラグを使用しない理由を示す優れた例です。

修正

プログラムが短い場合、おそらく最も簡単で迅速な修正方法は、単にプログラムを再度インデントすることです。各ステートメントがインデントレベルごとに4つのスペースでインデントされていることを確認します(コードをインデントするにはどうすればよいですか?)。

ただし、タブとスペースを混在させた大きなプログラムが既にある場合は、すべてのインデントをスペースに変換するために使用できる自動化ツールがあります。

PyCharmSublimeText などの多くのエディターには、タブをスペースに自動的に変換するオプションがあります。 Tabs To SpacesBrowserling などのオンラインツールもあり、コードをすばやく再インデントできます。 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を発生させますが、上記のコードのreal問題は、2番目のpassステートメントがインデントされる必要があることです。 2番目のpassはインデントされていないため、Pythonは、前のifステートメントとelseステートメントが接続されていることを認識しません。

このタイプのエラーの修正は、コードを単純に正しくインデントし直すことです。コードを適切にインデントする方法については、「コードをインデントするにはどうすればよいですか?」セクションを参照してください。

私はまだPythonのインデント構文に苦労しています。私は何をしますか?

まだ苦労しているのでがっかりしないでください。 Pythonの空白の構文規則に慣れるには時間がかかる場合があります。役立つヒントを次に示します。

  • インデントエラーが発生したときに通知するエディターを入手します。いくつかの商品は、上記のとおり PyCharmSublimeText 、および Jupyter Notebook です。
  • コードをインデントするときは、スペースバー(またはタブキー)を何回押すかを自分で大声で数えます。たとえば、行を4スペース分インデントする必要がある場合は、「onetwothreefour」、同時にスペースバーを同時に押す馬鹿げているように聞こえますが、コードをインデントする深さを考えるように脳を訓練するのに役立ちます。
  • エディターがある場合は、タブをスペースに自動的に変換するオプションがあるかどうかを確認してください。
  • 他人のコードを表示します。 github または Stackoverflow を参照し、Pythonコードの例を参照してください。
  • コードを書くだけです。それが良くなるための唯一の最良の方法です。 Pythonコードを記述するほど、より良い結果が得られます。

使用したリソース

54
Christian Dean

崇高なテキスト3

Sublime Text 3でコーディングすると、インデントの問題を解決できます。

Sublime Textで、Pythonファイルの編集中:

Sublime Textメニュー> Preferences> Settings-Syntax Specific

Python.sublime-settings

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

Sublimeユーザー向けのクイックフィックス:

  1. Ctrl-Hを押して検索と置換にアクセスします
  2. 検索:タイプ4スペース
  3. 置換:コードのどこかからタブをコピーして貼り付けます[すべて置換]をクリックします
0
Matthew Park

ほら、小さなエラーがあります。

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

あなたがすることになっていた:

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

プリントが3スペース分だけインデントされていることがわかるように、4スペース分インデントされているはずです。

0
The Coder