エラノート エラノート

Python TypeErrorの原因と対処法まとめ

Python TypeError エラー解決 デバッグ
広告スペース (article-top)

PythonのTypeErrorは、データの型(type)が期待と合わないときに発生するエラーです。文字列と数値の結合、呼び出せないオブジェクトの呼び出し、関数の引数の数の間違いなど、原因はさまざまです。この記事では、TypeErrorのよくある発生パターンと対処法をエラーメッセージ別にコード例つきで解説します。

TypeErrorとは

TypeErrorは、あるオブジェクトに対して、その型ではサポートされていない操作を行ったときに発生する組み込み例外です。

エラーメッセージの読み方

result = "合計: " + 100
# TypeError: can only concatenate str (not "int") to str

このメッセージは「str型にはstr型しか結合できません(int型はできません)」という意味です。エラーメッセージには「何の型に対して」「何が問題なのか」が書かれているので、まずはメッセージを正確に読みましょう。

TypeErrorが発生する主なケース

TypeErrorは大きく3つのカテゴリに分けられます。

  • 異なる型同士の演算(文字列と数値の加算など)
  • 呼び出せないオブジェクトの呼び出し(int型を関数として呼ぶなど)
  • 関数の引数に関するエラー(引数の数や型の不一致)

パターン1: 文字列と数値の結合

最も多いTypeErrorの一つです。Pythonでは文字列と数値を+演算子で直接結合できません。

エラーの例

name = "田中"
age = 25

# NG: 文字列とint型は結合できない
message = name + "さんは" + age + "歳です"
# TypeError: can only concatenate str (not "int") to str

対処法: 型変換またはf文字列を使う

name = "田中"
age = 25

# 対処法1: str()で型変換
message = name + "さんは" + str(age) + "歳です"

# 対処法2: f文字列(推奨)
message = f"{name}さんは{age}歳です"

# 対処法3: format()メソッド
message = "{}さんは{}歳です".format(name, age)

print(message)  # 田中さんは25歳です

f文字列を使えば、型変換を意識する必要がなく最も簡潔に書けます。

パターン2: 数値同士の型の不一致

異なる処理を期待して型が合わないケースです。

intとstrの演算

# NG: input()の戻り値はstr型
price = input("価格を入力: ")  # "500"(文字列)
tax = price * 1.1
# TypeError: can't multiply sequence by non-int of type 'float'

# OK: int()またはfloat()で変換
price = int(input("価格を入力: "))
tax = price * 1.1
print(tax)  # 550.0

リストと文字列の演算

# NG: リストと文字列は結合できない
items = [1, 2, 3]
result = items + "4"
# TypeError: can only concatenate list (not "str") to list

# OK: リストにはリストを結合する
result = items + [4]
print(result)  # [1, 2, 3, 4]

パターン3: 呼び出せないオブジェクトの呼び出し

関数ではないオブジェクトを関数のように()で呼び出すとTypeErrorになります。

変数名と関数名の衝突

# NG: 変数名が組み込み関数を上書きしてしまった
list = [1, 2, 3]   # 変数名にlistを使用
new_list = list()   # 組み込み関数のlist()が使えなくなる
# TypeError: 'list' object is not callable

# OK: 組み込み関数名を変数名に使わない
numbers = [1, 2, 3]
new_list = list()  # 組み込み関数が正常に動作する

よくある組み込み関数名の誤用パターンは、listdictstrinttypeprintなどです。これらを変数名に使わないようにしましょう。

プロパティを関数として呼び出す

# NG: len は関数、.length ではない(Pythonにはlength属性はない)
text = "hello"
print(text.length())
# AttributeError: 'str' object has no attribute 'length'

# OK: len()関数を使う
print(len(text))  # 5
# NG: 整数を関数として呼び出す
count = 10
result = count()
# TypeError: 'int' object is not callable

# OK: 変数をそのまま使う
result = count

パターン4: 関数の引数の数が合わない

関数が期待する引数の数と実際に渡した引数の数が異なるとTypeErrorが発生します。

引数が多い

def greet(name):
    return f"こんにちは、{name}さん"

# NG: 引数が多い
greet("田中", "太郎")
# TypeError: greet() takes 1 positional argument but 2 were given

このメッセージは「greet()は位置引数を1つ取りますが、2つ渡されました」という意味です。

引数が足りない

def add(a, b):
    return a + b

# NG: 引数が足りない
add(10)
# TypeError: add() missing 1 required positional argument: 'b'

クラスのメソッドでselfを忘れる

class Calculator:
    # NG: selfを書き忘れている
    def add(a, b):
        return a + b

calc = Calculator()
calc.add(1, 2)
# TypeError: Calculator.add() takes 2 positional arguments but 3 were given

calc.add(1, 2)は内部的にCalculator.add(calc, 1, 2)として呼ばれるため、3つの引数が渡されることになります。

class Calculator:
    # OK: selfを第1引数にする
    def add(self, a, b):
        return a + b

calc = Calculator()
print(calc.add(1, 2))  # 3

パターン5: イテラブルでないオブジェクトの反復

forループで反復できないオブジェクトを使うとTypeErrorになります。

intをforループに渡す

# NG: int型はイテラブルではない
for i in 5:
    print(i)
# TypeError: 'int' object is not iterable

# OK: range()を使う
for i in range(5):
    print(i)

NoneTypeの反復

# NG: sort()はNoneを返す
numbers = [3, 1, 4, 1, 5]
for n in numbers.sort():
    print(n)
# TypeError: 'NoneType' object is not iterable

# OK: sort()は元のリストを変更する(戻り値はNone)
numbers = [3, 1, 4, 1, 5]
numbers.sort()
for n in numbers:
    print(n)

# OK: sorted()を使えば新しいリストが返る
numbers = [3, 1, 4, 1, 5]
for n in sorted(numbers):
    print(n)

パターン6: 添字アクセスできないオブジェクト

[]で要素にアクセスできないオブジェクトに対して添字アクセスするとTypeErrorになります。

NoneTypeに添字アクセス

# NG: 関数がNoneを返している場合
def get_data():
    print("データ取得中")
    # returnを書き忘れている(Noneが返る)

result = get_data()
print(result[0])
# TypeError: 'NoneType' object is not subscriptable

# OK: 関数で値をreturnする
def get_data():
    return [1, 2, 3]

result = get_data()
print(result[0])  # 1

intに添字アクセス

# NG: 数値に[]でアクセス
num = 12345
first_digit = num[0]
# TypeError: 'int' object is not subscriptable

# OK: 文字列に変換してからアクセス
num = 12345
first_digit = str(num)[0]
print(first_digit)  # "1"

デバッグ: type関数で型を確認する

TypeErrorに遭遇したら、type()関数で変数の型を確認するのが最初の一歩です。

data = input("数値を入力: ")
print(type(data))  # <class 'str'>  ← str型だとわかる

# 型がわかれば適切な変換ができる
data = int(data)
print(type(data))  # <class 'int'>

isinstance()を使えば、事前に型をチェックして安全に処理することもできます。

def process(value):
    if not isinstance(value, (int, float)):
        raise TypeError(f"数値が必要です(渡された型: {type(value).__name__})")
    return value * 2

まとめ

PythonのTypeErrorについて、よくある発生パターンと対処法を解説しました。

  • 文字列と数値の結合にはf文字列やstr()を使う
  • input()の戻り値はstr型なので、計算にはint()やfloat()で変換する
  • 組み込み関数名(listdictなど)を変数名に使わない
  • クラスのメソッドには第1引数にselfを忘れずに書く
  • sort()などNoneを返すメソッドの戻り値をそのまま使わない
  • type()関数でデバッグ時に変数の型を確認する

エラーメッセージには「どの型に対して」「何が問題なのか」が明記されています。メッセージを正確に読む習慣をつけることが、素早いエラー解決への近道です。

広告スペース (article-bottom)

あわせて読みたい