エラノート エラノート

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

Python AttributeError エラー解決 デバッグ オブジェクト
広告スペース (article-top)

PythonのAttributeErrorは、オブジェクトに存在しない属性(メソッドやプロパティ)にアクセスしようとしたときに発生するエラーです。メソッド名のスペルミスやNone型への操作など原因は多岐にわたります。この記事ではよくある発生パターンと対処法をコード例とともに解説します。

AttributeErrorとは

AttributeErrorは、あるオブジェクトが持っていない属性(attribute)を参照しようとしたときに発生する例外です。Pythonではすべてのデータがオブジェクトであり、それぞれが固有の属性を持っています。

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

text = "hello"
text.append("world")
# AttributeError: 'str' object has no attribute 'append'

このメッセージは「str型のオブジェクトにはappendという属性がありません」という意味です。appendはリストのメソッドであり、文字列には存在しません。

エラーメッセージの構成

AttributeError: '<型名>' object has no attribute '<属性名>'
  • 型名: 操作対象のオブジェクトの型
  • 属性名: アクセスしようとした属性の名前

この2つの情報から「どの型に対して」「何をしようとして失敗したか」がわかります。

パターン1: メソッド名のスペルミス

最も単純で多いパターンです。メソッド名を1文字でも間違えるとAttributeErrorになります。

# NG: メソッド名のスペルミス
numbers = [3, 1, 4, 1, 5]
numbers.apped(9)
# AttributeError: 'list' object has no attribute 'apped'

# OK: 正しいメソッド名
numbers.append(9)
# NG: 大文字小文字の間違い
text = "Hello World"
result = text.Upper()
# AttributeError: 'str' object has no attribute 'Upper'

# OK: メソッド名は小文字
result = text.upper()
print(result)  # "HELLO WORLD"

対処法: dir関数で属性一覧を確認する

# オブジェクトが持つ属性を確認
text = "hello"
# アンダースコアで始まらない属性のみ表示
public_attrs = [attr for attr in dir(text) if not attr.startswith("_")]
print(public_attrs)
# ['capitalize', 'casefold', 'center', 'count', 'encode', ...]

対処法: hasattr関数で事前チェックする

# 属性の存在を確認してからアクセス
obj = "hello"
if hasattr(obj, "append"):
    obj.append("world")
else:
    print(f"{type(obj).__name__}にappendメソッドはありません")
# strにappendメソッドはありません

パターン2: NoneTypeのAttributeError

関数がNoneを返すケースを見落とすと、Noneに対してメソッドを呼び出してしまいAttributeErrorが発生します。

# NG: リストのsortメソッドはNoneを返す
numbers = [3, 1, 4, 1, 5]
sorted_numbers = numbers.sort()  # sort()はNoneを返す
print(sorted_numbers.count(1))
# AttributeError: 'NoneType' object has no attribute 'count'

破壊的メソッドと非破壊的メソッドの違い

# sort()は元のリストを変更してNoneを返す(破壊的)
numbers = [3, 1, 4, 1, 5]
numbers.sort()  # 戻り値はNone
print(numbers)  # [1, 1, 3, 4, 5]

# sorted()は新しいリストを返す(非破壊的)
numbers = [3, 1, 4, 1, 5]
sorted_numbers = sorted(numbers)  # 新しいリストが返る
print(sorted_numbers)  # [1, 1, 3, 4, 5]
print(numbers)         # [3, 1, 4, 1, 5](元のリストは変わらない)

Noneを返す代表的なメソッド

以下のメソッドは戻り値がNoneです。戻り値を変数に代入して使おうとするとAttributeErrorの原因になります。

# list.sort(), list.append(), list.extend(), list.reverse()
# dict.update(), dict.clear()
# set.add(), set.discard()

# NG: appendの戻り値を使おうとする
items = [1, 2, 3]
result = items.append(4)  # resultはNone
print(result)  # None

パターン3: 型の取り違え

変数に想定と異なる型の値が入っているケースです。

# NG: 文字列だと思ったらリストだった
data = ["apple", "banana", "cherry"]
print(data.split(","))
# AttributeError: 'list' object has no attribute 'split'

# OK: リストを文字列に結合してからsplitする場合
text = ",".join(data)
print(text.split(","))  # ['apple', 'banana', 'cherry']
# NG: 辞書だと思ったら文字列だった(JSONの未パース)
import json
response = '{"name": "太郎", "age": 25}'
print(response.get("name"))
# AttributeError: 'str' object has no attribute 'get'

# OK: JSONをパースしてから辞書としてアクセス
data = json.loads(response)
print(data.get("name"))  # 太郎

type関数で型を確認する

# デバッグ時は型を確認する習慣をつける
data = some_function()
print(type(data))  # <class 'NoneType'> など
print(data)        # 値の確認

パターン4: モジュールのAttributeError

モジュールに存在しない関数や定数にアクセスしようとするとAttributeErrorになります。

# NG: モジュールに存在しない関数を呼ぶ
import math
result = math.square(16)
# AttributeError: module 'math' has no attribute 'square'

# OK: 正しい関数名を使う
result = math.sqrt(16)
print(result)  # 4.0

バージョン違いによるAttributeError

Pythonのバージョンによって使える機能が異なります。

# Python 3.9以降で使える型ヒント
# Python 3.8以前ではAttributeErrorになる場合がある
import sys
print(sys.version)  # バージョンを確認

# Python 3.9以降
# result: list[int] = [1, 2, 3]

# Python 3.8以前はtypingモジュールが必要
# from typing import List
# result: List[int] = [1, 2, 3]

自作モジュールの名前衝突

# NG: ファイル名がモジュール名と衝突
# random.pyというファイル名にしてしまうと
import random
result = random.randint(1, 10)
# AttributeError: module 'random' has no attribute 'randint'
# → 自分のrandom.pyが読み込まれてしまう

# 対策: ファイル名を標準ライブラリと被らない名前にする
# 例: my_random.py, dice.py など

パターン5: クラス定義でのAttributeError

クラスのインスタンスに存在しない属性へアクセスするケースです。

# NG: 定義していない属性にアクセス
class User:
    def __init__(self, name, age):
        self.name = name
        self.age = age

user = User("太郎", 25)
print(user.email)
# AttributeError: 'User' object has no attribute 'email'

__init__での初期化漏れ

# NG: 条件分岐の中でしか属性を設定していない
class User:
    def __init__(self, name, age, email=None):
        self.name = name
        self.age = age
        if email:
            self.email = email  # emailがNoneだと属性が作られない

user = User("太郎", 25)
print(user.email)
# AttributeError: 'User' object has no attribute 'email'

# OK: 条件に関わらず属性を初期化する
class User:
    def __init__(self, name, age, email=None):
        self.name = name
        self.age = age
        self.email = email  # Noneでも属性を作る

user = User("太郎", 25)
print(user.email)  # None

getattr関数で安全にアクセスする

user = User("太郎", 25)

# getattrでデフォルト値を指定
email = getattr(user, "email", "未設定")
print(email)  # "未設定"

デバッグの手順

AttributeErrorに遭遇したときの調査手順をまとめます。

手順1: エラーメッセージの型名と属性名を確認する

# エラー例
# AttributeError: 'NoneType' object has no attribute 'split'

# → NoneType に split を呼んでいる
# → 変数がNoneになっている原因を調べる

手順2: 問題の変数の型と値を出力する

data = get_data()
print(f"型: {type(data)}, 値: {data}")
# 型: <class 'NoneType'>, 値: None
# → get_data()がNoneを返していることがわかる

手順3: 使える属性を確認する

data = get_data()
if data is not None:
    print(dir(data))

まとめ

AttributeErrorは「オブジェクトに存在しない属性へアクセスした」ときに発生します。主な原因と対処法は以下の通りです。

  • メソッド名のスペルミスや大文字小文字の間違いを確認する
  • Noneを返すメソッド(sortappendなど)の戻り値を使っていないか確認する
  • type関数やprintで変数の型と値を確認する
  • hasattrgetattrで安全に属性へアクセスする
  • モジュール名と自作ファイル名の衝突に注意する

エラーメッセージの「型名」と「属性名」を正確に読み取ることが、原因特定への最短ルートです。

広告スペース (article-bottom)

あわせて読みたい