こんにちは。PyQチームのtsutomuです。
今回は「集合を扱うデータ型のset
で、要素のオブジェクトが重複しない理由」を解説します。
質問:setを使うとなぜオブジェクトが重複しないのか?
Pythonの
set
を使って、下記のように、2回オブジェクト(以下では123
)を追加しました。しかし出力すると{123}
のように1つしかありません。なぜ、そうなるのか詳しく教えてください。
set1 = set() # 空のset set1.add(123) set1.add(123) # 同じオブジェクトを追加 print(set1) # 1つだけ「{123}」と出力
回答:set
が重複しない理由
setは集合を表すデータ構造です。重複しない要素の集まりを表現するための型なので、同じオブジェクトを複数持つことはできません。
setでは、オブジェクトが追加されるときに「既に同じオブジェクトがあるかどうか」を確認して、異なるオブジェクトだけが追加されます。
それはオブジェクトを追加するときに、既に同じオブジェクトがあるかを確認して、異なるオブジェクトだけを追加するからです。
同じオブジェクトかを確認するには、ハッシュ値を使って効率的に確認できるようになっています。
ハッシュ値は、ハッシュ関数(hash()
)を使って計算します。
print(hash(123)) # 123 print(hash('123')) # -3322108026846747911
ハッシュ関数は、上記のようにオブジェクトを引数にして整数のハッシュ値を求める関数です。-3322108026846747911
というハッシュ値は、Pythonを起動するたびに値が異なることに注意してください(Pythonを起動している間はハッシュ値は変わりません)。
仮に、異なるオブジェクトのハッシュ関数が同じ値になっても問題ありません。ハッシュ値が同じオブジェクトは、さらに同値かどうかを比較します。追加しようとしたオブジェクトが、既に存在するオブジェクトと異なる値であれば、別のオブジェクトと判断され追加されます。
なお、ハッシュ関数で計算できないオブジェクトは、そもそもset
に追加できません。
たとえば、変更可能(ミュータブル)なオブジェクトであるリストは、以下のようにhash()
を使うとエラーになります。つまり、リストはset
に追加できません。
hash([]) # TypeError: unhashable type: 'list'
ハッシュ可能なオブジェクトには、数値や文字列などがあります。
また、リストはハッシュ可能ではありませんが、(ハッシュ可能な要素を持つ)タプルはハッシュ可能です。
エラー「TypeError: unhashable type: 'list'」については下記の記事も参考にしてください
set
については下記も参考にしてください
関連するクエスト
このお悩み解決はPyQのクエスト「setのメソッドの使い方を学ぼう」の1問目の補足情報として作成しています。