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
これらのエラーはどういう意味ですか?私は何を間違えていますか?コードを修正するにはどうすればよいですか?
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を使用すると、これらの警告はエラーになります。これらのオプションを強くお勧めします!
問題
このエラーは、ステートメントが不必要にインデントされるか、そのインデントが同じブロック内の以前のステートメントのインデントと一致しない場合に発生します。たとえば、次のプログラムの最初のステートメントは不必要にインデントされています。
>>> 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.
...
問題
このエラーは、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.
...
>>>
問題
このエラーは、ステートメントのインデントを解除したときに発生しますが、そのステートメントのインデントレベルは以前のステートメントのインデントレベルと一致しなくなりました。たとえば、次のコードでは、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
を取得している場合は、タブにスペースが混在している可能性があります。これにより、Pythonが奇妙なエラーを引き起こすことがあります。 特別な場合のサブセクションWhat's "TabError :インデントでのタブとスペースの一貫性のない使用」は、問題のより詳細な説明については、を意味します。
問題
このエラーは、インデント文字としてタブとスペースを混在させようとした場合にのみ発生します。上記のように、Pythonでは、プログラムにタブとスペースを混在させることはできず、特定の例外TabError
が見つかった場合は例外が発生します。たとえば、次のプログラムでは、タブとスペースの組み合わせがインデントに使用されます。
>>> if True:
... if True:
... print()
... print()
... print()
File "<stdin>", line 5
print()
^
TabError: inconsistent use of tabs and spaces in indentation
上記のプログラムの空白を視覚的に示す写真を次に示します。灰色のドットはスペース、灰色の矢印はタブです。
実際、インデント用のスペースとタブが混在していることがわかります。
特殊なケース
注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つのスペースでインデントされていることを確認します(コードをインデントするにはどうすればよいですか?)。
ただし、タブとスペースを混在させた大きなプログラムが既にある場合は、すべてのインデントをスペースに変換するために使用できる自動化ツールがあります。
PyCharm や SublimeText などの多くのエディターには、タブをスペースに自動的に変換するオプションがあります。 Tabs To Spaces や Browserling などのオンラインツールもあり、コードをすばやく再インデントできます。 Pythonで書かれたツールもあります。 autopep8 たとえば、コードやその他のインデントエラーも自動的に再インデントできます。
ただし、最良のツールであっても、すべてのインデントエラーを修正できない場合があり、手動で修正する必要があります。そのため、コードを最初から常に適切にインデントすることが重要です。
頻繁ではありませんが、インデントが正しくないために、特定の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の空白の構文規則に慣れるには時間がかかる場合があります。役立つヒントを次に示します。
Sublime Text 3でコーディングすると、インデントの問題を解決できます。
Sublime Textで、Pythonファイルの編集中:
Sublime Textメニュー> Preferences> Settings-Syntax Specific:
Python.sublime-settings
{
"tab_size": 4,
"translate_tabs_to_spaces": true
}
Sublimeユーザー向けのクイックフィックス:
ほら、小さなエラーがあります。
if True:
if False:
print('foo')
print('bar')
あなたがすることになっていた:
if True:
if False:
print('foo')
print('bar')
プリントが3スペース分だけインデントされていることがわかるように、4スペース分インデントされているはずです。