AttributeError(属性エラー)の原因と解決法|Python初心者向けにわかりやすく解説

Pythonを学習していると、よく遭遇するエラーの一つが「AttributeError(属性エラー)」です。

AttributeError: '〇〇' object has no attribute '〇〇'

このエラーはPython初心者にとって特にわかりにくいエラーの一つですが、意味を理解すると原因をかなり簡単に特定できるようになります。

この記事では、AttributeErrorの意味から、具体的な原因、解決方法、よくある間違いまで、Python初心者にもわかりやすく解説します。

AttributeErrorとは?

AttributeErrorとは、オブジェクトに存在しない属性やメソッドへアクセスしたときに発生するエラーです。

例えば、次のコードを実行してみましょう。

name = "Python"

print(name.upper())

このコードでは、文字列に用意されているupper()メソッドを使用しているため、正常に動作します。

一方、存在しないメソッドを呼び出すとAttributeErrorが発生します。

name = "Python"

print(name.hello())

実行すると、次のようなエラーになります。

AttributeError: 'str' object has no attribute 'hello'

これは、

str型のオブジェクトにはhelloという属性・メソッドはありません

という意味です。

AttributeErrorの読み方

AttributeErrorが発生したら、まずエラーメッセージを確認しましょう。

AttributeError: 'str' object has no attribute 'hello'

このメッセージには重要な情報が含まれています。

'str' object

これは、エラーが発生したオブジェクトの型を表しています。

今回の場合は、

str

つまり文字列です。

has no attribute 'hello'

これは、

hello

という属性・メソッドが存在しないという意味です。

したがって、

AttributeError: 'str' object has no attribute 'hello'

は、

「文字列型のオブジェクトにhelloという属性・メソッドは存在しません」

と読み取れます。

エラーメッセージから原因を引く

よく出るメッセージを先に並べます。自分が見ているメッセージを探してください。いずれも実際に実行して出した結果です。

メッセージ 何が起きているか 直し方
'str' object has no attribute 'append' 文字列にリストのメソッドを使っている 文字列は変更できない。s + "d" で新しい文字列を作る
'list' object has no attribute 'add' リストに集合のメソッドを使っている append()(1件)かextend()(複数)
'dict' object has no attribute 'append' 辞書にリストのメソッドを使っている d[key] = value で追加する
'tuple' object has no attribute 'append' タプルは変更できない リストに変換するか、最初からリストで持つ
'NoneType' object has no attribute '...' 値がNone。関数が何も返していない可能性が高い 関数にreturnがあるか確認する
'int' object has no attribute 'upper' 数値を文字列と思っている str(n) で変換してから使う
module 'math' has no attribute 'sqr' モジュールにその名前の関数が無い 正しい名前を確認する(math.sqrt)
'User' object has no attribute 'nama' 自分で定義した属性の綴りちがい __init__ で代入した名前と見比べる

has no attribute の前に出ている型('str' object の部分)がいま実際に入っている値の型です。ここが自分の想定と違っていたら、属性名ではなく値のほうを疑います。

AttributeErrorが発生する主な原因

AttributeErrorが発生する原因はいくつかあります。

代表的なのは次の5つです。

  1. 存在しないメソッドを呼び出している
  2. メソッド名・属性名を間違えている
  3. オブジェクトの型を勘違いしている
  4. 属性を定義していない
  5. Noneに対してメソッドを呼び出している

順番に見ていきましょう。

1. 存在しないメソッドを呼び出している

最も基本的な原因です。

例えば、次のコードを見てみましょう。

name = "Python"

name.reverse()

すると、次のようなエラーになります。

AttributeError: 'str' object has no attribute 'reverse'

Pythonの文字列にはreverse()というメソッドが存在しないためです。

文字列を逆順にしたいのであれば、スライスを使って次のように書けます。

name = "Python"

print(name[::-1])

実行結果は次のとおりです。

nohtyP

2. メソッド名や属性名を間違えている

AttributeErrorでは、スペルミスも非常に多い原因です。

例えば、次のコードを実行するとエラーになります。

name = "Python"

print(name.lenght())

正しくは、文字列の長さを取得する場合、len()関数を使用します。

name = "Python"

print(len(name))

また、Pythonでは大文字と小文字も区別されます。

次のコードは正しい書き方です。

name.upper()

一方、次のように書くとエラーになります。

name.Upper()

upperとUpperは別の名前として扱われるためです。

そのため、次のようなAttributeErrorが発生します。

AttributeError: 'str' object has no attribute 'Upper'

AttributeErrorが発生したら、まず「メソッド名や属性名を間違えていないか?」を確認するとよいでしょう。

3. オブジェクトの型を勘違いしている

AttributeErrorでは、自分が想定していた型と、実際の型が違うというケースも非常に多くあります。

例えば、次のコードを考えてみましょう。

data = "100"

print(data.append("200"))

append()はリストで使用するメソッドです。

しかし、dataは文字列です。

次のコードを使えば、変数の型を確認できます。

print(type(data))

実行結果は次のようになります。

<class 'str'>

リストとして扱いたいのであれば、次のようにします。

data = ["100"]

data.append("200")

print(data)

実行結果:

['100', '200']

4. 自分で定義した属性が存在しない

クラスを使っている場合、自分で定義した属性が存在しないことでもAttributeErrorが発生します。

例えば、次のコードを見てみましょう。

class User:
    def __init__(self, name):
        self.name = name

user = User("太郎")

print(user.age)

このコードでは、Userクラスにageという属性を定義していません。

そのため、次のエラーが発生します。

AttributeError: 'User' object has no attribute 'age'

ageを使用するのであれば、あらかじめ属性を定義します。

class User:
    def __init__(self, name, age):
        self.name = name
        self.age = age

user = User("太郎", 30)

print(user.age)

実行結果:

30

5. Noneに対してメソッドを呼び出している

Python初心者がAttributeErrorで特に悩みやすいのが、Noneに対してメソッドを呼び出しているケースです。

例えば、次のコードです。

name = None

print(name.upper())

すると、次のエラーが発生します。

AttributeError: 'NoneType' object has no attribute 'upper'

これは、NoneTypeにはupper()という属性・メソッドが存在しないという意味です。

なぜNoneになるのか?

例えば、関数の戻り値を受け取っているケースがあります。

def get_name():
    print("太郎")

name = get_name()

print(name.upper())

get_name()ではreturnを書いていません。

Pythonでは、関数が明示的に値を返さない場合、戻り値はNoneになります。

つまり、次のコードのnameにはNoneが入っています。

name = get_name()

確認するには、次のようにします。

print(name)
print(type(name))

AttributeErrorの解決方法

AttributeErrorを解決するときは、闇雲にコードを修正するのではなく、「エラーが発生したオブジェクトの正体を確認する」ことが重要です。

1. type()で型を確認する

まず、type()を使って型を確認してみましょう。

print(type(data))

例えば、次のコードでは、

data = "Python"

print(type(data))

次のように表示されます。

<class 'str'>

リストだと思っていたのにstrだった、といった問題を発見できます。

2. dir()で使用できる属性を確認する

Pythonには、オブジェクトが持っている属性やメソッドを確認するためのdir()があります。

name = "Python"

print(dir(name))

すると、文字列が持っているメソッドなどを確認できます。

例えば、次のようなメソッドが確認できます。

  • upper
  • lower
  • replace
  • split
  • strip

「このオブジェクトにはどんなメソッドがあるのだろう?」と確認したいときに便利です。

3. エラーメッセージを読む

AttributeErrorが発生したら、エラー文をそのまま読む習慣をつけましょう。

AttributeError: 'list' object has no attribute 'upper'

この場合は、次のように読み取れます。

  • list型に対して
  • upperという属性・メソッドを
  • 使用しようとしている
  • しかし、listには存在しない

この情報だけでも、原因をかなり絞り込めます。

よくあるAttributeErrorの例

listにadd()を使ってしまう

次のコードは正常に動作します。

numbers = [1, 2, 3]

numbers.append(4)

print(numbers)

listにはappend()が用意されているためです。

しかし、次のようにadd()を使うとエラーになります。

numbers = [1, 2, 3]

numbers.add(4)

結果:

AttributeError: 'list' object has no attribute 'add'

add()はリストのメソッドではありません。

文字列にappend()を使ってしまう

text = "Python"

text.append("!")

これもAttributeErrorになります。

AttributeError: 'str' object has no attribute 'append'

append()はリストなどで使うメソッドであり、文字列にはありません。

Noneに対してlower()を使う

text = None

print(text.lower())

結果:

AttributeError: 'NoneType' object has no attribute 'lower'

この場合は、textがなぜNoneになったのかを調べる必要があります。

module ‘X’ has no attribute ‘Y’ が出たとき

オブジェクトではなくモジュールに対して出るパターンです。原因は3つあります。

1. 関数名が違う

いちばん多いのは単純な綴りちがいです。

import math
math.sqr(4)

実行結果:

  File "cases.py", line 21, in mod
    math.sqr(4)
AttributeError: module 'math' has no attribute 'sqr'

正しくは math.sqrt(4) です。そのモジュールに何があるかは print(dir(math)) で一覧できます。

2. 自分のファイル名が標準ライブラリとぶつかっている

これがいちばん気づきにくい原因です。自分で random.py というファイルを作ると、import random が標準ライブラリではなく自分のファイルを読み込みます。

# 自分で作った random.py
value = 42
# use_random.py
import random
print(random.randint(1, 10))

実行結果:

  File "use_random.py", line 2, in <module>
    print(random.randint(1, 10))
AttributeError: module 'random' has no attribute 'randint'

random.randint は確かに存在するのに「無い」と言われます。読み込まれたのが自分のファイルだからです。ファイル名を変える(my_random.py など)のが直し方で、同じディレクトリに残っている __pycache__ も消しておきます。

ぶつかりやすい名前は random.py json.py time.py math.py string.py email.py test.py あたりです。

3. ライブラリのバージョンで属性が消えた

外部ライブラリを更新したあとに出る場合は、その属性が別名に変わったか削除された可能性があります。インストールされている版を確かめて、公式の変更履歴と見比べます。

python3 -m pip show パッケージ名
python3 -c "import パッケージ名 as m; print(m.__version__)"

AttributeErrorを出さない書き方

原因を直すだけでなく、そもそも落ちない書き方にしておく方法があります。

属性があるか先に確かめる

class User:
    def __init__(self, name):
        self.name = name

u = User("佐藤")
print("hasattr(u, 'name') =", hasattr(u, 'name'))
print("hasattr(u, 'age')  =", hasattr(u, 'age'))
print("getattr(u, 'age', 0) =", getattr(u, 'age', 0))

実行結果:

hasattr(u, 'name') = True
hasattr(u, 'age')  = False
getattr(u, 'age', 0) = 0

hasattr() は属性の有無を真偽値で返します。getattr(オブジェクト, 名前, 既定値) は第3引数を付けると属性が無いときに例外ではなく既定値を返します。

Noneが混ざる値を安全に扱う

names = ["佐藤", None, "鈴木"]
print([n.upper() if n else "" for n in names])

実行結果:

['佐藤', '', '鈴木']

None が混ざりうる値は、メソッドを呼ぶ前に必ず分岐させます。上の例は日本語なので upper() の結果が変わりませんが、落ちずに通ることが確認できます。

辞書は属性ではなくキーで引く

d = {"name": "佐藤"}
print(d.get('age', 0))

実行結果:

0

d.name と書くと 'dict' object has no attribute 'name' になります。辞書は d["name"] か、キーが無いかもしれないときは d.get("name", 既定値) です。

Python 3.10以降は候補を出してくれる

Python 3.10以降では、綴りが近い属性があるとエラーメッセージの最後に Did you mean: ... という候補が付きます。綴りちがいの特定がかなり楽になるので、学習用の環境は新しめのPythonにしておくと得です。(この記事の実行結果は3.9.6で取っているため、上の例には候補が出ていません)

AttributeErrorと他のエラーの違い

Pythonにはさまざまなエラーがあります。AttributeErrorと混同しやすいエラーを確認しておきましょう。

エラー 主な意味
AttributeError 存在しない属性・メソッドを使用した
TypeError 型が適切ではない
NameError 存在しない変数名を使用した
IndexError 存在しないインデックスを指定した
KeyError 存在しない辞書のキーを指定した
ValueError 値の種類・内容が適切ではない
SyntaxError Pythonの文法が間違っている

例えば、次のコードを考えてみましょう。

numbers = [1, 2, 3]

print(numbers[10])

これは存在しないインデックスを指定しているため、IndexErrorです。

一方、次のコードでは、

numbers = [1, 2, 3]

numbers.add(4)

リストに存在しないaddという属性・メソッドを呼び出しているため、AttributeErrorになります。

AttributeErrorを効率的に解決する手順

AttributeErrorが発生したら、次の順番で確認すると効率的です。

STEP1:エラーが発生した行を確認する

AttributeError: 'str' object has no attribute 'hello'

まず、エラーが発生したコードの行を確認します。

STEP2:対象オブジェクトを確認する

print()とtype()を使って確認します。

print(data)
print(type(data))

STEP3:属性名・メソッド名を確認する

例えば、次のコードでエラーが発生した場合、

data.hello()

helloというメソッドが本当に存在するのかを確認します。

STEP4:dir()を使う

dir()を使えば、そのオブジェクトが持っている属性やメソッドを確認できます。

print(dir(data))

STEP5:Noneになっていないか確認する

特に、次のようなエラーが出た場合は注意しましょう。

AttributeError: 'NoneType' object has no attribute ...

この場合は、対象の変数がNoneになった原因を調べる必要があります。

AttributeErrorを恐れないことがプログラミング上達につながる

AttributeErrorは、Pythonを使っていると頻繁に遭遇するエラーです。

しかし、エラーそのものを怖がる必要はありません。

例えば、

AttributeError: 'str' object has no attribute 'append'

と表示されたら、

「str型にappendは使えないんだな」

と判断できます。

つまり、エラーメッセージは単なる「失敗のお知らせ」ではなく、プログラムを修正するためのヒントでもあります。

特に初心者のうちは、次の3つを覚えておくと、エラーの原因を自分で見つけやすくなります。

print(type(data))
print(data)
print(dir(data))

関連記事

あわせて読むと理解が深まります。

まとめ

AttributeErrorは、オブジェクトに存在しない属性やメソッドへアクセスしたときに発生するエラーです。

代表的な原因は次のとおりです。

  • 存在しないメソッドを呼び出している
  • メソッド名や属性名を間違えている
  • オブジェクトの型を勘違いしている
  • クラスの属性を定義していない
  • Noneに対してメソッドを呼び出している

解決するときは、まず次のコードで型を確認してみましょう。

print(type(data))

さらに、利用できる属性やメソッドを確認する場合は、dir()が便利です。

print(dir(data))

「エラーが出た=失敗」ではなく、「エラーメッセージからプログラムの状態を確認できる」と考えると、Pythonのデバッグが一気に楽になります。

AttributeErrorを一つずつ自分で解決できるようになることは、Pythonの基礎力を高めるうえでも重要です。

テックジムPython基礎コース(初心者向け)

人気のPython講座・スクールならテックジム|初心者におすすめの実践型Python講座

 

他のPythonエラーの原因と対処法はPythonエラー一覧と対処法に種類別でまとめています。エラーメッセージの読み方もあわせて解説しています。

プログラミング学習に興味がある方は、まずは無料体験会へ

無料体験会・お申し込みはこちら