私は、リストのような解けない型は突然変異しているので、ハッシュの鍵として使うことはできないことを理解しています。しかし、私はなぜ彼らのメモリアドレス(私は変更を信じていない)が使用できるのか分からない。例えばDictのキーとして、非ハッシュタイプのメモリアドレスを使用できないのはなぜですか?
:
my_list = [1,2,3]
my_dict = {my_list: 1} #error
my_dict = {id(my_list): 1} # no error
私は、リストのような解けない型は突然変異しているので、ハッシュの鍵として使うことはできないことを理解しています。しかし、私はなぜ彼らのメモリアドレス(私は変更を信じていない)が使用できるのか分からない。例えばDictのキーとして、非ハッシュタイプのメモリアドレスを使用できないのはなぜですか?
:
my_list = [1,2,3]
my_dict = {my_list: 1} #error
my_dict = {id(my_list): 1} # no error
あなた実際あなたがlist
を拡張する場合など、set
、ハッシュ関数のようなオブジェクトのメモリアドレスを使用することができます
メモリアドレスを使用して第一の理由2つのオブジェクトが等しい場合(a == b
がTrue
と評価されるため)、ハッシュ値が同じである(hash(a) == hash(b)
〜True
)ようにしたいからです。さもなければ、意図しない振る舞いをする可能性があります。
この例を見るには、list
を拡張する独自のクラスを作成し、そのオブジェクトのメモリアドレスをハッシュ関数として使用しましょう。
>>> class HashableList(list):
def __hash__(self):
return id(self) # Returns the memory address of the object
ここで、2つのハッシュ可能リストを作成できます。私たちのHashableList
は、pythonのビルトインリストと同じコンストラクタを使います。
>>> a = HashableList((1, 2, 3))
>>> b = HashableList((1, 2, 3))
案の定、私たちが期待するように、我々は
>>> a == b
True
を取得し、我々は我々のリストをハッシュすることができます!
>>> hash(a)
1728723187976
>>> hash(b)
1728723187816
>>> hash(a) == hash(b)
False
あなたは最後の3桁の数字を見れば、あなたが表示されますa
とb
は、メモリ内の互いに近接しているが、同じ場所にはありません。我々はハッシュとしてメモリアドレスを使用しているので、ハッシュ値が等しくないことも意味します。
2つの等しいタプル(または他のハッシュ可能オブジェクト)の組み込みハッシュを比較するとどうなりますか?
>>> y = ('foo', 'bar')
>>> z = ('foo', 'bar')
>>> y == z
True
>>> hash(y)
-1256824942587948134
>>> hash(z)
-1256824942587948134
>>> hash(y) == hash(z)
True
あなた自身でこれをしようとすると、文字列のハッシュは毎回のpythonが始まるの新しいセッションを変更するので、('foo', 'bar')
のあなたのハッシュは、地雷とは一致しません。重要なことは、同じセッションでhash(y)
は常にhash(z)
と等しいことです。
私たちがセットを作って、HashableList
のオブジェクトと作ったタプルで遊んでみましょう。
>>> s = set()
>>> s.add(a)
>>> s.add(y)
>>> s
{[1, 2, 3], ('foo', 'bar')}
>>> a in s # Since hash(a) == hash(a), we can find a in our set
True
>>> y in s # Since hash(y) == hash(y), we can find y in our set
True
>>> b in s
False
>>> z in s
True
でもa == b
かかわらず、hash(b)
が等しいhash(a)
ないので、我々はセットでa
を見つけることができなかったので、我々はセットで私たちの同等のリストを見つけることができませんでした!
これらはディクテーションではありません。プラス 'id()'は 'int'を返すので、なぜ動作しないのでしょうか? –
整数をハッシングしています。 –
簡単にはできますが、 '{some_list:whatever} 'はそれをしません。なぜなら、それはdictsのセマンティクスを壊すからです。 – user2357112