Python学習チャンネル by PyQ

Pythonのオンライン学習プラットフォームPyQのオフィシャルブログです

【Pythonお悩み解決】AttributeError: 'NoneType' object has no attribute 'group' とは何ですか?

こんにちは、PyQサポートです。

今回は AttributeError: 'NoneType' object has no attribute 'group' というエラーの意味と、その解消方法を解説します。
reモジュールを使った時に、このエラーになることがあります。
早速、質問を見ていきましょう。

質問 AttributeError: 'NoneType' object has no attribute 'group'というエラーはどういうものですか?

AttributeError: 'NoneType' object has no attribute 'group' というエラーが出ました。どのように直したら良いでしょうか?

入力した内容(コード)

import re

text = "Hello"
m = re.match("Hi", text)
print(m.group(0))

出たエラー(実行結果)

Traceback (most recent call last):
  File "/Users/pyq/scripts/match.py", line 5, in <module>
    print(m.group(0))
AttributeError: 'NoneType' object has no attribute 'group'

回答 検索パターンにマッチしない場合を考慮していないために起きたエラーです

AttributeError: 'NoneType' object has no attribute 'group'は、AttributeError (属性エラー)というエラーで、そのオブジェクトに存在しない属性を参照しようとすると発生するエラーです。

今回の場合はmNoneオブジェクトであったため、このエラーが発生しました。
Noneは「何もない」ことを表すオブジェクトであり、属性を持ちません)

ではなぜ mNoneだったのでしょうか?

それには、reモジュールのmatch()関数について知る必要があります。

match() 関数の使い方

reモジュールのmatch() 関数の基本的な使い方は以下のとおりです(import re は省略しています)。

マッチ結果 = re.match(検索パターン, 対象文字列)

match()関数は「対象文字列」の先頭部分が「検索パターン」とマッチすれば、マッチ結果として「マッチオブジェクト」を返します。

しかし、マッチしないとNoneを返します。

今回のコードでは、"Hi""Hello"と先頭部分がマッチしないため、マッチ結果であるmNoneになりました。

text = "Hello"
m = re.match("Hi", text)  # m は None になる

mNoneなので、m.groups(0)AttributeErrorが発生します。

このように検索パターンにマッチしない場合を考慮していなかったことが、今回のエラーの原因といえるでしょう。

マッチしなかった場合にエラーを回避するには

このエラーを回避する方法は、大きく2つあります。

1つは、try ... except文を使って、AttributeErrorを処理する方法です。もう1つは、Python 3.8から導入された代入式を使う方法です。

代入式を使うほうがシンプルに書けますので、今回はこちらの方法を紹介します。

代入式は:=(セイウチ演算子と呼ばれます)を使って記述され、変数に値を代入するとともに、代入結果を返します。

代入式を使って修正したコードは以下のとおりです(このコードは実行しても何も表示されません)。

import re

text = "Hello"
if m := re.match("Hi", text):
    print(m.group(0))

m := re.match("Hi", text)が代入式を使っている箇所です。マッチ結果がNoneの場合、if文の判定でFalse扱いとなります。そのためm.group(0)は実行されず、エラーを回避できます。

ちなみに、代入式の部分を代入式を使わずに書くと、以下のようになります。

# 代入式を使わないと2行になる
m = re.match("Hi", text)
if m:
    print(m.group(0))

代入式により「文字列検索」と「マッチ結果の判定」を1行で記述でき、コードをより簡潔に書けることが分かると思います。

なお、代入式については過去のブログ記事でも解説していますので、下部の参考リンクをご参照ください。

補足: match()関数とsearch()関数

今回の例ではreモジュールのmatch()関数を使いましたが、reモジュールにはsearch()関数というものもあります。

基本的な使い方はmatch()関数と同じです。

マッチ結果 = re.search(検索パターン, 対象文字列)

この2つの関数の違いは、match()関数が文字列の先頭がパターンにマッチするかを調べるのに対し、search()関数は先頭に限らずマッチする部分があるかを調べるところです。

場合に応じて使い分けるとよいでしょう。

参考リンク

match()関数の公式ドキュメント

docs.python.org

search()関数の公式ドキュメント

docs.python.org

group()関数の公式ドキュメント

docs.python.org

代入式についての過去のブログ記事

blog.pyq.jp

Copyright ©2017- BeProud Inc. All rights reserved.