上級のPythonエラー 30問
10種類のエラーを、それぞれ複数パターンずつ収録しています。
- 可変デフォルト引数が呼び出しをまたいで共有されるリストや辞書をデフォルト引数にすると、その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な値を見落とします。