以下は現場でよく見るミスを分かりやすくまとめたチェックリストです。コードを書いたらこの順でサッと確認するとミスを減らせます。各項目は「問題」「なぜダメ」「どう直す」の3点で短く示します。
- 1) 変数名ルール違反(無効な識別子)
- 2) Pythonの予約語/組み込み関数を上書きしてしまう
- 3) 定義前に使ってしまう(NameError / UnboundLocalError)
- 4) タイプの勘違い(型エラー)
- 5) = と == の混同(代入と比較)
- 6) 意図せぬ参照渡し(可変オブジェクトの共有)
- 7) 関数のデフォルト引数に可変オブジェクトを使う
- 8) スコープ(global / local)の勘違い
- 9) タイポ(スペルミス)によるバグ
- 10) None の比較を == でしてしまう
- 11) 浮動小数点の等値比較(==)に注意
- 12) モジュール名と変数名の衝突
- 13) 多重代入/アンパックのミス
- 14) 意図しない型変換(暗黙の変換を期待する)
- 15) デバッグ不足:原因を特定できない
- ✅ おまけ:簡単チェックフロー(作業前・コードレビュー用)
1) 変数名ルール違反(無効な識別子)
- 問題:
1count = 5やtotal-price = 100 - なぜダメ:名前は英字/数字/
_のみ。数字で始められない。記号や空白は不可。 - 直し方:
count1、total_priceにする。
2) Pythonの予約語/組み込み関数を上書きしてしまう
- 問題:
list = [1,2,3]やinput = "hi" - なぜダメ:組み込みが使えなくなり後で混乱する(例:
list()が使えない)。 - 直し方:
items、user_inputのように別名を使う。エディタの警告に注意。
3) 定義前に使ってしまう(NameError / UnboundLocalError)
- 問題:
print(x)を先に書いてからx = 10 - なぜダメ:変数がまだ存在しないからエラー。関数内での代入はローカル扱いで更に注意。
- 直し方:使う前に必ず代入する。関数内でグローバル変数を変更するなら
globalを検討(多用は避ける)。
4) タイプの勘違い(型エラー)
- 問題:
"10" + 5をそのまま実行 →TypeError - なぜダメ:文字列と数値は直接足せない。
- 直し方:
int("10") + 5またはf"{10} + {5}"のように型を整える/変換する。
5) = と == の混同(代入と比較)
- 問題:
if x = 10:を書いてしまう(Pythonでは構文エラー) - なぜダメ:
=は代入、==は比較。条件式では比較を使う。 - 直し方:
if x == 10:にする。Python 3.8+ の代入式(:=)は用途を理解した上で使う。
6) 意図せぬ参照渡し(可変オブジェクトの共有)
- 問題:
a = [1,2]; b = a; b.append(3)→aも変わる - なぜダメ:リストや辞書は参照渡し。コピーしたつもりが別名になっていることがある。
- 直し方:コピーが必要なら
b = a.copy()(浅コピー)やimport copy; b = copy.deepcopy(a)を使う。
7) 関数のデフォルト引数に可変オブジェクトを使う
- 問題:
def f(x=[]):
x.append(1)
return x
Python呼ぶたびに結果が蓄積される。
- なぜダメ:デフォルト引数は関数定義時に一度だけ作られる。
- 直し方:
def f(x=None):
if x is None:
x = []
x.append(1)
return x
Python8) スコープ(global / local)の勘違い
- 問題:関数内でグローバル変数を変更しようとして
UnboundLocalErrorが出る。 - なぜダメ:関数内で代入があるとその名前はローカル変数扱いになり、参照時に未定義扱いになる。
- 直し方:ローカルで別名を使うか、どうしてもグローバルを変更するなら
global varnameを明示(ただし推奨度は低め)。
9) タイポ(スペルミス)によるバグ
- 問題:
total_priceをtotal_prceとタイプミス → NameError / 意図しない別値 - なぜダメ:静かに別変数ができるケースもありバグになりやすい。
- 直し方:エディタのオートコンプリート・リンターを使う。テストや print/type() で確認。
10) None の比較を == でしてしまう
- 問題:
if x == None: - なぜダメ:
Noneは同一性チェックが望ましい。 - 直し方:
if x is None:/if x is not None:を使う。
11) 浮動小数点の等値比較(==)に注意
- 問題:
0.1 + 0.2 == 0.3が False になることがある。 - なぜダメ:浮動小数点は内部表現で誤差が出る。
- 直し方:丸めるか
math.isclose()を使う(厳密等価を期待しない)。
12) モジュール名と変数名の衝突
- 問題:
import mathのあとにmath = 2としてしまう。 - なぜダメ:モジュールが参照できなくなる(
math.sqrtが消える)。 - 直し方:モジュール名は上書きしない。別名を付ける場合は
import math as mを使う(ただし変数名 m も注意)。
13) 多重代入/アンパックのミス
- 問題:
a, b = [1, 2, 3]→ ValueError(要素数が違う) - なぜダメ:アンパックする要素数が一致しないとエラー。
- 直し方:
a, *rest = [1,2,3]や要素数を合わせる。
14) 意図しない型変換(暗黙の変換を期待する)
- 問題:
"10" * 3が"101010"になって驚く(文字列の繰り返し)。 - なぜダメ:演算結果は型依存。期待と違う動きになることがある。
- 直し方:意図が数値なら
int("10") * 3。文字列として扱うならそのままでOK。
15) デバッグ不足:原因を特定できない
- 問題:エラーが出てもどの変数が原因か不明。
- 直し方(ツール的対策):
print(var, type(var))で中身と型を確認。- エディタのリンター(flake8, pylint)や型チェッカー(mypy)を使う。
- 小さな単位で動かして(ユニットテスト/REPLで試す)から大きな処理に組み込む。
✅ おまけ:簡単チェックフロー(作業前・コードレビュー用)
- 変数名は読みやすいか?(意味ある名前)
- 予約語・組み込みを上書きしていないか?
- 使う前に必ず定義しているか?(関数スコープも確認)
- 可変オブジェクトのコピーが必要か?(参照になってないか)
- デフォルト引数にリスト/辞書を使っていないか?
is None/==/==の使い分けは適切か?- 型のミスマッチはないか?(
type()でチェック) - テストまたは簡単な実行で値の流れを確認したか?
