【Pythonエラー解決】TypeError: unhashable typeって何?辞書のキーに使えないものの正体
こんにちは。ゆうせいです。
Pythonでデータを扱う上で、辞書(dictionary)は本当に便利ですよね!キー
とバリュー
をペアで管理できるので、プログラムの色々な場面で大活躍します。
文字列や数字をキーにすることは、みなさんよくやっていると思います。ですが、こんな風に考えたことはありませんか?
「リストをキーにできないかな?」
「もし使ったら、どんなエラーが出るんだろう?」
実は、Pythonの辞書のキーには「使えるもの」と「使えないもの」に明確なルールが存在します。このルールを知らないと、TypeError: unhashable type
という、一見すると謎のエラーに遭遇してしまうかもしれません。
今回は、この辞書のキーに関するたった一つの大事なルールを、例え話を交えながら徹底的に解説していきます!
結論:辞書のキーは「変更不可能なもの」しか使えない!
いきなり結論からいきましょう。辞書のキーにできるもののルールは、たった一つです。
それは、「イミュータブル(immutable)であること」。
…いきなり専門用語が出てきましたね。大丈夫、難しくありませんよ!
「イミュータブル」とは、ひと言でいうと「一度作ったら、中身を変更できない」という性質のことです。
たとえるなら、一度現像した「写真」のようなものです。写真に写っている人や風景を、後から変えることはできませんよね。これがイミュータブルのイメージです。
逆に、中身を自由に変えられる性質のことを「ミュータブル(mutable)」と言います。こちらは「ホワイトボード」を想像してください。書いたり消したり、自由に内容を変更できます。
Pythonの主なデータ型をこの2種類に分けると、以下のようになります。
イミュータブルな型(キーに使える!)
int
(整数)float
(浮動小数点数)str
(文字列)bool
(真偽値True
,False
)tuple
(タプル)
ミュータブルな型(キーに使えない!)
list
(リスト)dict
(辞書)set
(セット)
そう、キーに使えないものの代表格はリスト、辞書、セットなんです。
なぜ?キーが変更不可能でなければならない理由
「でも、なんでそんなルールがあるの?」と思いますよね。その理由を理解することが、エラーを根本から解決する一番の近道です!
Pythonの辞書は、目的のデータを非常に高速に見つけ出す仕組みを持っています。その秘密が「ハッシュ値」というものです。
ハッシュ値とは、データから計算される、そのデータを表すための「指紋」のようなものだと考えてください。Pythonは、辞書にデータを追加するとき、キーの「指紋(ハッシュ値)」を計算し、その指紋とデータを関連付けて保管します。
そしてデータを取り出すときは、指定されたキーの指紋を再度計算し、「この指紋のデータはどこかな?」と一瞬で探し当てるのです。
ここで、もしキーが変更可能(ミュータブル)だったらどうなるでしょう?
リスト [1, 2] をキーとして辞書に登録したとします。Pythonは [1, 2] の指紋を計算してデータを保管します。
しかし、その後であなたが my_list.append(3) のようにリストの中身を [1, 2, 3] に変えてしまったら…?
大変です!指紋の元となるデータが変わってしまったので、もう同じ指紋は作れません。Pythonは「あれ?最初に登録された指紋のデータが見つからない!」と大混乱に陥ってしまいます。
まるで、合鍵を作ったのに、後から家の鍵穴の形が変わってしまったようなものです。もう二度と家には入れませんよね。
このような大混乱を防ぐために、Pythonは「指紋が変わってしまう可能性のあるもの(=ミュータブルな型)は、キーとして登録できません!」という厳しいルールを設けているのです。
そして、このルールを破った時に表示されるのが、あのエラーメッセージです。
TypeError: unhashable type: 'list'
これは直訳すると「リストという型は、ハッシュ化(指紋を計算)できません」という意味だったのですね。
実際に試してみよう!
ルールが分かったところで、実際にコードで確認してみましょう。
キーとして使える例
# 文字列、整数、タプルはイミュータブルなのでOK
ok_dict = {
"name": "Yusei",
100: "Price",
(10, 20): "Coordinate"
}
print(ok_dict)
キーとして使えない例(エラー発生)
# リストはミュータブルなのでNG
ng_list = [1, 2, 3]
try:
ng_dict = {ng_list: "This will fail"}
except TypeError as e:
print(f"エラーが発生しました: {e}")
実行結果:
エラーが発生しました: unhashable type: 'list'
見事にTypeError
が発生しましたね!
まとめと今後の学習指針
今回の内容をまとめます。
- 辞書のキーになれるのはイミュータブル(変更不可能)な型だけ。
- なぜなら、Pythonはキーのハッシュ値(指紋)を使ってデータを高速管理しているから。
- キーの中身が変わるとハッシュ値も変わり、データを見失ってしまうため。
- リスト、辞書、セットはミュータブル(変更可能)なのでキーには使えない。
TypeError: unhashable type
は「そのデータ型はハッシュ化できませんよ」というサイン。
この「イミュータブル」と「ミュータブル」の区別は、Pythonプログラミングにおいて非常に重要な概念です。関数の引数で意図せず値が書き換わってしまう問題など、他の場面でもこの知識があなたを助けてくれるでしょう。
もし「リストをどうしてもキーのように使いたい!」という状況になったら、一度タプルに変換する tuple(my_list)
ことを検討してみてください。タプルはイミュータブルなので、キーとして安心して使えますよ。
データ型の性質をしっかり理解して、エラーを恐れず、さらにPythonの世界を楽しんでいきましょう!