エラーの内容
Pythonスクリプトが以下のエラーでクラッシュします:
TypeError: unsupported operand type(s) for +: 'int' and 'str'
Pythonは整数と文字列の間で + を使おうとしたことを検出し、処理を拒否しました。JavaScriptやPHPとは異なり、Pythonは暗黙的な型変換を一切行いません。明示的に型を指定する必要があります。これは実はバグではなく、仕様です。微妙なデータ破損を防ぐためのものです。
よくあるシナリオ
シナリオ1:ユーザー入力と数値の混在
input() は常に文字列を返します。ユーザーが 25 と入力しても同様です:
age = input("年齢を入力してください: ") # '25'を返す(25ではない)
years = 10
print("10年後の年齢は " + age + years) # ❌ TypeError
シナリオ2:数値変数を使った文字列の構築
count = 42
message = "合計アイテム数: " + count # ❌ TypeError
シナリオ3:ファイル、API、データベースからのデータ
CSVファイル、JSONレスポンス、データベースドライバは数値に見える値を文字列として返すことがよくあります。経験豊富な開発者でもはまりやすい落とし穴です:
row = {"price": "99", "tax": "8"}
total = row["price"] + row["tax"] # "998"が返る(107ではない)— 数値計算ではなく文字列結合
クイックフィックス
修正1:整数を文字列に変換して結合する
メッセージを構築する場合は、数値を str() で囲みます:
count = 42
message = "合計アイテム数: " + str(count) # ✅ "合計アイテム数: 42"
修正2:文字列を整数に変換して計算する
計算を行う場合は、先に int() で変換します:
age = input("年齢を入力してください: ") # "25"
years = 10
future_age = int(age) + years # ✅ 35
修正3:f文字列を使う(最もすっきりした方法)
f文字列は手動変換なしで値を直接埋め込めます。モダンなPythonのやり方です:
count = 42
message = f"合計アイテム数: {count}" # ✅ str()不要
age = int(input("年齢を入力してください: "))
years = 10
print(f"10年後の年齢は {age + years}")
恒久的な修正:型変換を安全に処理する
input()の結果は即座に変換する
初心者が陥りがちなミス:入力を文字列として読み込み、20行後に変換し忘れること。取得した時点で変換しましょう:
# 悪い例 — 忘れやすい
raw = input("価格を入力してください: ")
# ... 20行のコード ...
total = raw + 5 # ❌ TypeError(バグの発生場所から遠く離れた箇所で起きる)
# 良い例 — その場で変換する
price = float(input("価格を入力してください: ")) # ✅ ここからpriceはfloat型
total = price + 5 # ✅ 入力が"5"なら10.0
外部ソースからのデータを検証・変換する
制御外のデータが来る場合はヘルパー関数で変換をラップします:
def safe_add(a, b):
try:
return int(a) + int(b)
except (ValueError, TypeError) as e:
raise TypeError(f"{type(a).__name__}と{type(b).__name__}は加算できません: {e}")
row = {"price": "99", "tax": "8"}
total = safe_add(row["price"], row["tax"]) # ✅ 107
文字列構築には+の代わりにf文字列を使う
+ による文字列結合は、値が文字列でない瞬間に壊れます。f文字列にはその心配がありません:
# 壊れやすい — すべての変数に手動でstr()が必要
result = "スコア: " + str(score) + "/" + str(total) + " (" + str(pct) + "%)"
# 堅牢 — 型を気にしなくていい
result = f"スコア: {score}/{total} ({pct}%)"
デバッグ:型の不一致がどこで起きているかを探す
エラーがコードの深い場所で発生する場合、どの変数が間違った型かすぐには分かりません。type() を使って確認しましょう:
a = get_value_from_somewhere()
b = get_another_value()
print(type(a), type(b)) # 例:
result = a + b
さらに、アサーションを追加することで、混乱を招くエラーが別の場所で発生する前に型の不一致を検出できます:
assert isinstance(a, int), f"intを期待しましたが{type(a).__name__}が渡されました: {a!r}"
assert isinstance(b, int), f"intを期待しましたが{type(b).__name__}が渡されました: {b!r}"
修正の確認
以下のコードを実行して、すべて正常に動作することを確認します:
# エラーをキャッチする(クラッシュしない)
try:
result = 10 + "5"
except TypeError as e:
print(f"エラーをキャッチしました: {e}")
# 15を出力するはず
result = 10 + int("5")
print(result) # 15
# "Value: 10"を出力するはず
result = "Value: " + str(10)
print(result) # Value: 10
修正済みのコードはいずれも例外を発生させることなく、期待される出力を表示するはずです。
まとめ
- 数値を含む文字列を構築する場合は
str(数値)を使います。 - 文字列の値で計算を行う場合は
int(文字列)またはfloat(文字列)を使います。 +による結合よりもf文字列を優先しましょう。型を自動的に処理してくれます。input()、ファイル、APIから取得した値は、何十行も後回しにせず、読み込んだ時点で変換しましょう。

