AttributeError: 'NoneType' object has no attribute の原因と直し方[Python]
Pythonで最も遭遇率の高いエラーのひとつがこれになる。
AttributeError: 'NoneType' object has no attribute 'append'属性名の部分はsplitだったりgroupだったりstripだったりと変わるが、原因はどれも同じで、Noneに対して何かをしようとしている。
Noneは値がないことを表す特別なオブジェクトで、文字列やリストのようなメソッドを持っていない。だから問題は「なぜそこがNoneになったのか」を突き止めることになる。
1. その場で書き換える関数の戻り値を受け取っている
いちばん多い原因がこれになる。
lst = [3, 1, 2]lst = lst.sort() # sort() は None を返すlst.append(4) # AttributeErrorsortはリスト自身を並べ替えて、戻り値としてはNoneを返す。同じ性質を持つメソッドは多い。
・list.sort() list.append() list.reverse() list.extend()
・dict.update()
・set.add() set.discard()
いずれも元のオブジェクトを書き換えるだけで、結果を返さない。代入しないのが正しい使い方になる。
lst.sort() # これでlstが並び替わる新しいリストが欲しい場合は、元を変えない関数のほうを使う。
new = sorted(lst) # sorted() は新しいリストを返す2. 正規表現がマッチしなかった
re.searchやre.matchは、見つからなければNoneを返す。
m = re.search(r"\d+", text)print(m.group()) # マッチしないと AttributeError見つからない場合を必ず書く。
m = re.search(r"\d+", text)if m: print(m.group())else: print("見つからない")既定値が欲しいだけなら、こう書ける。
num = m.group() if m else "0"3. 辞書のgetが既定値を返した
dict.getはキーがないときNoneを返す。
name = data.get("name")print(name.upper()) # キーが無いと AttributeError既定値を明示すれば防げる。
name = data.get("name", "")print(name.upper())キーが必ずあるべきならdata["name"]と書いたほうがいい。無いときにKeyErrorで止まるので、原因が分かりやすくなる。
4. 関数がreturnを書き忘れている
自作の関数で、条件によってreturnに到達しないケースがある。
def find_user(users, uid): for u in users: if u["id"] == uid: return u # 見つからないとき、暗黙のうちに None が返る
user = find_user(users, 5)print(user["name"]) # AttributeError や TypeErrorPythonの関数はreturnがないと自動的にNoneを返す。見つからない場合の扱いを呼び出し側で書くか、例外を投げるかを決めておく。
user = find_user(users, 5)if user is None: raise ValueError(f"ユーザー {uid} が見つかりません")5. ライブラリの検索系メソッド
BeautifulSoupのfindなど、見つからないとNoneを返すものは多い。
title = soup.find("h1").text # h1が無いと AttributeErrorh1 = soup.find("h1")title = h1.text if h1 else ""pandasのdf.queryが空になった場合や、os.environ.getなども同じ構造になる。
原因の特定を早くする
どこでNoneになったかが分からないときは、直前で確認してしまうのが早い。
print(type(obj), repr(obj))obj.something()型を出せばNoneTypeかどうかが一目で分かる。連鎖している式では、途中で切って変数に入れると特定しやすくなる。
a = get_data()print(repr(a))b = a.parse()なおNoneかどうかの判定は== Noneではなくis Noneを使う。Noneはひとつしか存在しないので、同一性で比べるのが正しい。
📘 None の扱いのような基礎を一度まとめて押さえるなら、独習Python。
まとめ
・Noneにはメソッドが無いので、原因は「なぜそこがNoneになったか」に尽きる
・sort append updateなど、その場で書き換える系の戻り値はNone。代入してはいけない
・re.search、dict.get、soup.findは見つからないとNoneを返す。必ず分岐を書く
・自作関数はreturnに到達しない経路があると暗黙にNoneを返す
・判定はis None。原因が読めないときは直前でtype()とrepr()を出す
※本記事にはアフィリエイト広告を含みます。