PythonのTypeError「'NoneType' object is not iterable」エラーの原因と解決策を徹底解説
Pythonでは、値を持つオブジェクトのみを反復処理(イテレーション)できます。反復可能なオブジェクトは、その値がNoneでない場合にのみ次の要素へアクセスできるためです。Noneオブジェクトに対して反復処理を行おうとすると、TypeError: 'NoneType' object is not iterableというエラーが発生します。
この記事では、このエラーの意味と発生原因を解説し、実際のコード例を通して解決方法をわかりやすく紹介します。
TypeError: 'NoneType' object is not iterable とは
オブジェクトが反復可能であるためには、何らかの値を含んでいる必要があります。Noneはnull値(空の値)を表しており、反復処理の対象となるオブジェクトを一切含んでいないため、イテレーションできません。
ここで重要なのは、Noneオブジェクトと空の反復可能オブジェクト(空リストや空文字列)は別物だという点です。空のリストや文字列を反復処理しても、このエラーは発生しません。
リストや文字列は反復可能なデータ型を持っているからです。Pythonインタプリタは空のリストに遭遇しても、値が存在しないため単純に反復処理をスキップします。一方、None値は反復処理が不可能なため、インタプリタはエラーを返します。
このエラーは、関数を定義する際にreturn文で戻り値を返し忘れた場合によく発生します。
エラーが発生する具体例
生徒名のリストを受け取り、「E」で始まる名前だけを抽出してコンソールに出力するプログラムを作成してみましょう。
まず、生徒名をフィルタリングする関数を定義します。
def filter_students(class_names):
new_class_names = []
for c in class_names:
if c.startswith("E"):
new_class_names.append(c)
この関数はforループを使ってclass_namesリスト内の各要素を順番に調べ、各項目が「E」で始まるかどうかを確認します。「E」で始まる場合は、その名前をnew_class_namesリストに追加します。
次に、新しいリストを走査して各値をコンソールに出力する関数を作成します。
def show_students(class_names):
for c in class_names:
print(c)
続いて、検索対象となる生徒のリストを宣言し、filter_students関数に渡します。
students = ["Elena", "Peter", "Chad", "Sam"]
students_e_name = filter_students(students)
このコードはfilter_students関数を実行し、「E」で始まる名前の生徒をすべて抽出します。抽出結果はstudents_e_nameという変数に格納されます。最後にshow_students関数を呼び出して、新しい生徒リストを表示しましょう。
show_students(students_e_name)
コードを実行すると、次のようなエラーメッセージが表示されます。
Traceback (most recent call last):
File "main.py", line 14, in <module>
show_students(students_e_name)
File "main.py", line 8, in show_students
for c in class_names:
TypeError: 'NoneType' object is not iterable
エラーが発生してしまいました。
解決方法
show_students関数内でclass_names変数を反復処理しようとしたとき、コードはNone値を検出してエラーを発生させます。これは、引数として渡されたclass_namesの値がNoneだからです。
このエラーの原因は、filter_students関数が戻り値を返していないことにあります。filter_students関数の実行結果をstudents_e_name変数に代入した時点で、Noneが設定されてしまうのです。
このエラーを解決するには、filter_students関数にreturn文を追加して戻り値を返すようにします。
def filter_students(class_names):
new_class_names = []
for c in class_names:
if c.startswith("E"):
new_class_names.append(c)
# ここにreturn文を追加しました
return new_class_names
def show_students(class_names):
for c in class_names:
print(c)
students = ["Elena", "Peter", "Chad", "Sam"]
students_e_name = filter_students(students)
show_students(students_e_name)
これにより、new_class_namesの値がメインプログラムに正しく返されるようになります。
コードを実行して動作を確認してみましょう。
Elena
今度は、「E」で始まる名前の生徒が正常に出力されました。
NoneType例外を回避する方法
技術的には、値を反復処理する前にその値がNoneかどうかをチェックすることで、NoneType例外を回避することも可能です。以下のコードを見てみましょう。
def filter_students(class_names):
new_class_names = []
for c in class_names:
if c.startswith("E"):
new_class_names.append(c)
return new_class_names
def show_students(class_names):
if class_names is not None:
for c in class_names:
print(c)
students = ["Elena", "Peter", "Chad", "Sam"]
students_e_name = filter_students(students)
show_students(students_e_name)
show_students()関数は、class_namesを反復処理する前にNone値かどうかをチェックしているため、正常に実行されます。
しかし、ほとんどの場合、これはベストプラクティスとは言えません。NoneTypeエラーの根本的な原因は、コードの別の場所にある問題であることが多いからです。
プログラム全体に「is not None」チェックを追加してしまうと、別の関数でreturn文を書き忘れていることに気づけません。そのため、このエラーに遭遇した場合は、「is not None」チェックで例外を握りつぶすのではなく、エラーの根本原因を特定して修正するのが得策です。
まとめ
TypeError: 'NoneType' object is not iterableエラーは、値がNoneであるオブジェクトに対して反復処理を行おうとしたときに発生します。
このエラーを解決するには、反復処理しようとするすべての値に、文字列やリストなどの反復可能なオブジェクトが割り当てられていることを確認しましょう。今回の例では、関数にreturn文を追加し忘れたため、関数がリストではなくNoneを返していました。
これで、自分のコードでこのよくあるPythonエラーに遭遇したときも、自信を持って解決できるはずです。
-
JavaScriptのTypeError:「'undefined' is not an object」エラーの原因と対処法
「TypeError: undefined is not an object」というエラーは、値が undefined(未定義)のオブジェクトに対して、プロパティへのアクセスやメソッドの呼び出しを行った場合に発生します。 このエラーメッセージが表示されるのは Safari ブラウザのみという点に注意が必要です。Chrome や Firefox などのブラウザでは、同じ状況でも「Cannot read properties of undefined (reading xxx)」のような、少し異なる文言でエラーが出力されます。そのため、Safari でのみ発生するバグとして報告されることも多くあり
-
Pythonでリスト内のすべての値の出現回数が一意かどうかを確認する方法
正または負の整数を含むリスト nums が与えられたとき、配列内のすべての値の出現回数が一意(重複がない)であるかどうかを確認する必要があります。 例えば、入力が nums = [6, 4, 2, 9, 4, 2, 2, 9, 9, 9] の場合、出力は True になります。これは、6 が 1 回、4 が 2 回、2 が 3 回、9 が 4 回出現しており、すべての出現回数が互いに異なるためです。 この問題を解決するには、以下の手順に従います。 num_counts := 各値とその出現回数を格納する新しいマップ(辞書)を作成します occurrences := num_counts の