Pythonのエラーを直して覚える
実際に出力されるメッセージを読みながら、空欄を埋めて直します。全117問。間違えた問題は翌日・3日後・7日後に自動で再出題されます。
エラー別に調べる
初級
- IndentationError: expected an indented block の原因と直し方if・for・def・whileの本体を書き忘れたときに出る、Python学習者が最初につまずくエラーです。波括弧の代わりにインデントでブロックを表すPythonならではの挙動を整理します。
- SyntaxError: expected ':' の原因と直し方if・for・def・whileなど、ブロックを始める文の末尾にコロンを付け忘れたときに出るエラーです。他言語の波括弧に慣れていると忘れやすいポイントです。
- TabError: inconsistent use of tabs and spaces の原因と直し方同じブロックの中でタブとスペースを混在させたときに出るエラーです。エディタ上では同じ見た目になるため、コードを読むだけでは原因に気づけません。
- NameError: name 'x' is not defined の原因と直し方定義していない変数を参照したときに出る、最も頻出のエラーの一つです。タイプミス・宣言忘れ・似た名前との混同のパターンを整理します。
- SyntaxError: Missing parentheses in call to 'print' の原因と直し方Python 2の書き方(print文)をPython 3で使うと出るエラーです。printが「文」から「関数」に変わったことが原因です。
- SyntaxError: unterminated string literal の原因と直し方文字列を開いたクォートと同じ種類で閉じ忘れたときに出るエラーです。シングルクォートとダブルクォートを混在させたときにも起きます。
- SyntaxError: '(' was never closed の原因と直し方丸括弧・角括弧・波括弧の対応が崩れたときに出るエラーです。複数行にまたがる呼び出しや、関数呼び出しの中に別の括弧が入れ子になっている場合に見落としがちです。
- ZeroDivisionError: division by zero の原因と直し方0による除算・剰余算で発生する例外です。/ と // と % のいずれでも、分母や除数が0だと例外になります。
- TypeError: can only concatenate str (not "int") to str の原因と直し方文字列と数値を + で連結しようとしたときに出るエラーです。Pythonの + は両辺の型が揃っていないと使えません。
- TypeError: '>' not supported between instances の原因と直し方文字列と数値、あるいはNoneと数値など、比較できない型同士を比較しようとしたときに出るエラーです。
- SyntaxError: invalid syntax(if x = 5:)の原因と直し方条件式の中で = (代入)を使おうとしたときに出るエラーです。比較には == を使います。
- NameError: Did you mean 'True'? の原因と直し方True・False・Noneの大文字小文字を間違えたときに出るエラーです。変数名の大文字小文字の食い違いでも同じ形のエラーになります。
- IndexError: list index out of range の原因と直し方リストの範囲外の添字にアクセスしたときに出るエラーです。添字が0始まりであることの直接の帰結です。
- AttributeError: object has no attribute 'length' の原因と直し方他言語の.lengthや.size()の感覚でPythonのコレクションを扱おうとしたときに出るエラーです。Pythonでは長さの取得はlen()という組み込み関数に統一されています。
中級
- AttributeError: 'NoneType' object has no attribute の原因と直し方Noneに対してメソッドを呼び出したときに出るエラーです。関数が値を見つけられずNoneを返す場面や、辞書のgetでキーが無かった場合に起きやすいパターンです。
- AttributeError: object has no attribute(メソッド名タイプミス)の原因と直し方メソッド名の綴りミスや、他言語の命名習慣(add・trim・toUpperCaseなど)を持ち込んだときに出るエラーです。
- KeyError の原因と直し方辞書に存在しないキーへアクセスしたときに出るエラーです。大文字小文字の違いも別のキーとして扱われます。
- ValueError: invalid literal for int() with base 10 の原因と直し方int()に数字以外の文字を含む文字列を渡したときに出るエラーです。小数点表記や空文字列も変換できません。
- TypeError: missing 1 required positional argument の原因と直し方関数定義で必要な引数の数だけ、呼び出し時に値を渡していないときに出るエラーです。
- TypeError: takes N positional arguments but M were given の原因と直し方関数に定義されている数より多くの引数を渡したときに出るエラーです。
- TypeError: missing 1 required positional argument: 'self' の原因と直し方クラスのメソッドをインスタンスを介さずに呼び出したときに出るエラーです。selfには本来インスタンス自身が自動で渡されます。
- UnboundLocalError: cannot access local variable の原因と直し方関数内で変数に代入すると、Pythonはその変数を自動的にローカル変数とみなします。代入より前に参照すると発生します。
- TypeError: 'str' object does not support item assignment の原因と直し方文字列の一部を直接書き換えようとしたときに出るエラーです。Pythonの文字列は不変(immutable)です。
- // と / の違い(整数除算と真の除算)// は切り捨て除算、/ は常に浮動小数点数を返す真の除算です。小数の結果が欲しい場面で // を使うと、エラーなく結果だけが狂います。
- TypeError: 'tuple' object does not support item assignment の原因と直し方タプルの要素を書き換えようとしたときに出るエラーです。丸括弧のタプルと角括弧のリストは見た目が似ていますが、変更可能かどうかが根本的に違います。
- 関数内でグローバル変数を更新できない(globalキーワード忘れ)関数の中で変数に代入すると、その変数は既定でローカル変数になります。外側の変数を更新したいときはglobal宣言が必要です。
- 剰余演算 % の符号がJavaと異なる理由Pythonの%は除数の符号に合わせた結果を返します。Javaなど多くの言語は被除数の符号に合わせるため、負の数を扱うと結果が変わります。
- f忘れでf文字列が展開されないf文字列のfを書き忘れると、波括弧の中身は変数として展開されず、そのままの文字として表示されます。
- range()の範囲指定でループが1回分ずれるrange()の終端は指定した値を含みません。全要素を回すつもりでrange(len(...) - 1)のように書くと、最後の1つが抜け落ちます。
上級
- 可変デフォルト引数が呼び出しをまたいで共有されるリストや辞書をデフォルト引数にすると、その1つのオブジェクトが全ての呼び出しで共有されます。呼び出すたびに新しく作られるわけではありません。
- イテレート中のリスト変更で要素が飛ばされるforループでリストを走査しながら同じリストからremove()すると、要素の位置がずれて一部が処理から漏れます。
- RuntimeError: dictionary changed size during iteration の原因と直し方辞書をイテレート中にキーを追加・削除すると発生する例外です。リストと違い、辞書はサイズの変化を検出して例外を投げます。
- = で複製したつもりが同じリストを指している(浅いコピー)= はリストや辞書の複製ではなく、同じオブジェクトを指す別名を作るだけです。片方を変更すると、もう片方にも影響します。
- is と == の違い(小さい整数キャッシュで「たまたま動く」)isはオブジェクトの同一性、==は値の比較です。-5〜256の整数はキャッシュされ、isでもたまたま正しく動いてしまいます。
- RecursionError: maximum recursion depth exceeded の原因と直し方再帰関数に終了条件(ベースケース)が無い、または正しく機能していないときに発生します。再帰は必ずどこかで止まる条件が必要です。
- 0.1 + 0.2 が 0.3 にならない理由浮動小数点数は2進数で正確に表現できない値があり、計算結果にわずかな誤差が生じます。==での比較はほぼ確実に失敗します。
- クラス属性がインスタンス間で共有されるクラス直下に書いたリストや辞書は、全インスタンスで共有される1つのオブジェクトになります。インスタンスごとに独立させたい場合は__init__で作ります。
- except: だけで書くと本当のバグまで隠れるexcept:とだけ書くとあらゆる例外を捕まえてしまい、想定していたエラーだけでなく、コードの本当のバグ(NameErrorなど)まで静かに隠してしまいます。
- 0や空文字列を「値が無い」と誤判定してしまう0、空文字列、空リストはすべてfalsyですが、「値が渡されていない」こととは意味が違います。if x: で済ませると、意図的に渡されたfalsyな値を見落とします。