Python
 Computer >> コンピューター >  >> プログラミング >> Python

PythonのTypeError「object of type 'NoneType' has no len()」エラーの原因と解決法を徹底解説

len()メソッドは、文字列・リスト・辞書といったイテラブル(反復可能)なオブジェクトに対してのみ使用できます。これは、イテラブルなオブジェクトが値のシーケンスを保持しているためです。一方、None値に対してlen()メソッドを使おうとすると、「TypeError: object of type 'NoneType' has no len()」というエラーが発生します。

本記事では、このエラーの意味と仕組みを解説し、実際にエラーが発生する2つの具体例をもとに、自分のコードでエラーを解決する方法を紹介します。

TypeError: object of type 'NoneType' has no len()とは何か

NoneTypeとは、PythonにおけるNoneデータ型のことです。Noneには値のコレクションが含まれていないため、イテラブルなオブジェクト向けのlen()のようなメソッドをNone値に対して使うことはできません。Noneには子となる値が存在しないので、その長さを計算しようとしても不可能なのです。

このエラーは、主に次の2つの場面で発生します。

  • sort()などの組み込みメソッドがリストをインプレース(元のリストを直接)変更することを忘れている場合
  • 関数内でreturn文を書き忘れている場合

それでは、それぞれの原因を詳しく見ていきましょう。

原因①:組み込みメソッドがリストをインプレースで変更する

まず、学校の生徒情報を格納した辞書のリストを、最終テストの点数の昇順に並べ替えるプログラムを作成します。

最初に、生徒の名前と最新のテスト得点を含む辞書のリストを定義しましょう。

students = [
	{"name": "Peter", "score": 76 },
	{"name": "Richard", "score": 63 },
	{"name": "Erin", "score": 64 },
	{"name": "Miley", "score": 89 }
]

各辞書には2つのキーと値が含まれており、片方は生徒の名前、もう片方は直近のテストの得点に対応しています。次に、sort()メソッドを使って生徒のリストを並べ替えます。

def score_sort(s):
	return s["score"]

sorted_students = students.sort(key=score_sort)

ここでは「score_sort」という関数を定義し、各辞書から「score」の値を返すようにしています。そして、この関数をキーとしてsort()メソッドに渡すことで、辞書のリストを並べ替えています。

続いて、リストの長さを出力します。

print("There are {} students in the list.".format(len(sorted_students)))

さらに、forループを使って新しい辞書のリストをコンソールに出力します。

for s in sorted_students:
	print("{} earned a score of {} on their last test.".format(s["name"], s["score"]))

このコードは、「sorted_students」リスト内の各生徒について、直近のテストで何点取ったかを知らせるメッセージを出力するものです。それではコードを実行してみましょう。

Traceback (most recent call last):
  File "main.py", line 13, in <module>
	print("There are {} students in the list.".format(len(sorted_students)))
TypeError: object of type 'NoneType' has no len()

エラーが発生してしまいました。

この問題を解決するには、sort()メソッドの結果を「sorted_students」に代入している箇所を削除する必要があります。sort()メソッドはリストをインプレースで変更するため、新しいリストを作らないからです。

「sorted_students」の宣言を削除し、プログラムの残りの部分では「students」を使うように修正します。

students.sort(key=score_sort)

print("There are {} students in the list.".format(len(students)))

for s in students:
	print("{} earned a score of {} on their last test.".format(s["name"], s["score"]))

コードを実行するとどうなるでしょうか。

There are 4 students in the list.
Richard earned a score of 63 on their last test.
Erin earned a score of 64 on their last test.
Peter earned a score of 76 on their last test.
Miley earned a score of 89 on their last test.

今度はコードが正常に実行されました。まずリスト内の生徒の人数が表示され、続いて各生徒の名前と直近のテストの得点が、点数の昇順に出力されています。

原因②:return文の書き忘れ

次に、コードをよりモジュール化してみましょう。ソート処理を独立した関数に移動し、さらに各生徒のテスト得点情報を出力する関数も定義します。

まず、生徒のリストとソート用のヘルパー関数を定義します。ここでは先ほどのチュートリアルで使ったコードを流用します。

students = [
	{"name": "Peter", "score": 76 },
	{"name": "Richard", "score": 63 },
	{"name": "Erin", "score": 64 },
	{"name": "Miley", "score": 89 }
]

def score_sort(s):
	return s["score"]

次に、リストを並べ替える関数を記述します。

def sort_list(students):
	students.sort(key=score_sort)

最後に、各生徒の成績情報を表示する関数を定義します。

def show_students(new_students):
	print("There are {} students in the list.".format(len(new_students)))
	for s in new_students:
		 print("{} earned a score of {} on their last test.".format(s["name"], s["score"]))

コードを実行する前に、これらの関数を呼び出す必要があります。

new_students = sort_list(students)
show_students(new_students)

プログラムはまずsort_list()関数でリストを並べ替え、その後show_students()関数によって各生徒の情報をコンソールに出力する流れになっています。

それではコードを実行してみましょう。

Traceback (most recent call last):
  File "main.py", line 21, in <module>
	show_students(new_students)
  File "main.py", line 15, in show_students
	print("There are {} students in the list.".format(len(new_students)))
TypeError: object of type 'NoneType' has no len()

またもやエラーが発生しました。今回の原因は、「sort_list」関数にreturn文を書き忘れたことです。

sort_list()関数を呼び出す際、その戻り値を変数「new_students」に代入しています。この変数は、各生徒の情報を表示するshow_students()関数に渡されます。しかし、return文がないため関数はNoneを返し、その結果このエラーが発生したのです。このエラーを解決するには、sort_list()関数にreturn文を追加する必要があります。

def sort_list(students):
	students.sort(key=score_sort)
	return students

もう一度コードを実行してみましょう。

There are 4 students in the list.
Richard earned a score of 63 on their last test.
Erin earned a score of 64 on their last test.
Peter earned a score of 76 on their last test.
Miley earned a score of 89 on their last test.

期待どおりの出力が得られました。

まとめ

「TypeError: object of type 'NoneType' has no len()」というエラーは、値がNoneであるオブジェクトに対してlen()メソッドを使用しようとしたときに発生します。

このエラーを解決するには、まずsort()などの組み込みリストメソッドの戻り値を変数に代入していないか確認しましょう。それでも解決しない場合は、プログラム内のすべての関数に必要なreturn文が揃っているかを見直してください。

これであなたも、Pythonのプロのようにこの問題を解決できるはずです!

  1. 【初心者向け】Pythonのtype関数とisinstance関数でオブジェクトの型を判定する方法

    このチュートリアルでは、Pythonの組み込み関数であるtype()とisinstance()について解説します。これらの関数は、オブジェクトの型(データ型)を判定するために使用される、非常に重要な機能です。それぞれの使い方を順番に見ていきましょう。 type(object) — オブジェクトの型を取得する type()は、オブジェクトがどのクラス(型)に属しているかを調べるための関数です。例えば、値が5であるオブジェクトvalがある場合、その型はint(整数型)になります。type関数を使えば、この情報を簡単に取得できます。 基本的な手順 オブジェクトを初期化する type(objec

  2. Pythonオブジェクトの内部を確認する方法|type()・dir()など組み込み関数の使い方

    Pythonオブジェクトの内部情報を確認するための組み込み関数 Pythonには、任意のオブジェクトが持つ属性(アトリビュート)、プロパティ、メソッドなどの内部情報を調査するための強力な組み込み関数群が標準で用意されています。デバッグやコードの理解、リフレクション処理を行う際に非常に役立ちます。 主な組み込み関数は以下の通りです。 type() — オブジェクトの型(クラス)を返す dir() — オブジェクトの属性・メソッドの一覧を返す id() — オブジェクトの一意な識別値を返す getattr() — 指定した属性の値を取得する hasattr() — 属性が存在するかどうかを判定す