インターネットで検索してみましたが、ハッシュ可能という意味が見つかりませんでした。
彼らがオブジェクトと言うとき、hashable
またはhashable objects
それはどういう意味ですか?
インターネットで検索してみましたが、ハッシュ可能という意味が見つかりませんでした。
彼らがオブジェクトと言うとき、hashable
またはhashable objects
それはどういう意味ですか?
回答:
Python用語集から:
オブジェクトは、その存続期間中に決して変更されない(
__hash__()
メソッドが必要)ハッシュ値があり、他のオブジェクトと比較できる(__eq__()
または__cmp__()
メソッドが必要)場合、ハッシュ可能です。等しいと比較するハッシュ可能なオブジェクトは、同じハッシュ値を持つ必要があります。これらのデータ構造はハッシュ値を内部で使用するため、ハッシュ可能性により、オブジェクトがディクショナリキーおよびセットメンバーとして使用可能になります。
Pythonの不変の組み込みオブジェクトはすべてハッシュ可能ですが、変更可能なコンテナ(リストや辞書など)はハッシュ可能ではありません。ユーザー定義クラスのインスタンスであるオブジェクトは、デフォルトでハッシュ可能です。それらはすべて等しくないため、ハッシュ値は
id()
です。
hash value
ハッシュ値が今ある場合。あなたは、いくつかの例を与えることができます
__hash__()
。より一般的には、en.wikipedia.org / wiki / Hash_functionを
id(object)
16倍ですobject.__hash__()
。そのため、このバージョンの用語集の抜粋は正しくありません。ハッシュ値はではありませんがid()
、そこから派生しています(Python 2.7.12の更新されたドキュメントに実際に記載されています)。
hash((1, [2, 3]))
実際に見てみてください。用語集のエントリをハッシュ可能に修正するリクエストを投稿しました。
ここでのすべての回答には、Pythonでのハッシュ可能なオブジェクトの実用的な説明がありますが、最初にハッシュという用語を理解する必要があると思います。
ハッシュとは、大量のデータを格納してすばやくアクセスする高性能の擬似ランダムアクセスデータ構造を作成するために使用されるコンピュータサイエンスの概念です。
たとえば、電話番号が10,000あり、それらを配列(連続したメモリロケーションにデータを格納し、ランダムアクセスを提供するシーケンシャルデータ構造)に格納したいが、必要な量の連続していない場合があります。メモリの場所。
したがって、代わりにサイズ100の配列を使用し、ハッシュ関数を使用して値のセットを同じインデックスにマップできます。これらの値はリンクリストに格納できます。これにより、アレイと同様のパフォーマンスが得られます。
これで、ハッシュ関数は、配列のサイズで数を割り、残りをインデックスとして取るのと同じくらい簡単になります。
詳細については、https://en.wikipedia.org/wiki/Hash_functionを参照してください
ここに別の良いリファレンスがあります:http : //interactivepython.org/runestone/static/pythonds/SortSearch/Hashing.html
変更可能でないもの(変更可能であること、変更される可能性が高いこと)はハッシュ化できます。検索するハッシュ関数に加えて、クラスにハッシュ関数がある場合は、たとえば、dir(tuple)
そして__hash__
メソッドを探して、ここにいくつかの例があります
#x = hash(set([1,2])) #set unhashable
x = hash(frozenset([1,2])) #hashable
#x = hash(([1,2], [2,3])) #tuple of mutable objects, unhashable
x = hash((1,2,3)) #tuple of immutable objects, hashable
#x = hash()
#x = hash({1,2}) #list of mutable objects, unhashable
#x = hash([1,2,3]) #list of immutable objects, unhashable
不変タイプのリスト:
int, float, decimal, complex, bool, string, tuple, range, frozenset, bytes
変更可能なタイプのリスト:
list, dict, set, bytearray, user-defined classes
Ellipsis
も不変タイプであり、のキーとして使用できることを発見しましたdict
。
hash(MyClass)
__hash__
およびを実装している場合、ハッシュ可能__eq__
です。さらに、すべてのユーザー定義クラスは、これらのメソッドを実装している(したがってハッシュ可能である)。これは、object
(ユニバーサルベースクラス)からメソッドを継承しているためです。
Python用語集によると私の理解では、ハッシュ可能なオブジェクトのインスタンスを作成すると、変更不可能な値もインスタンスのメンバーまたは値に従って計算されます。たとえば、その値は次のようにdictのキーとして使用できます。
>>> tuple_a = (1,2,3)
>>> tuple_a.__hash__()
2528502973977326415
>>> tuple_b = (2,3,4)
>>> tuple_b.__hash__()
3789705017596477050
>>> tuple_c = (1,2,3)
>>> tuple_c.__hash__()
2528502973977326415
>>> id(a) == id(c) # a and c same object?
False
>>> a.__hash__() == c.__hash__() # a and c same value?
True
>>> dict_a = {}
>>> dict_a[tuple_a] = 'hiahia'
>>> dict_a[tuple_c]
'hiahia'
同じメンバーを持つため、tuple_aとtuple_cのハッシュ値は同じであることがわかります。dict_aのキーとしてtuple_aを使用すると、dict_a [tuple_c]の値が同じであることがわかります。つまり、dictのキーとして使用された場合、ハッシュ値は同じであるため、同じ値を返します。同じ。ハッシュ可能ではないオブジェクトの場合、メソッドハッシュはNoneとして定義されます。
>>> type(dict.__hash__)
<class 'NoneType'>
このハッシュ値は動的な方法ではなくインスタンスの初期化時に計算されると思います。そのため、不変オブジェクトのみがハッシュ可能です。お役に立てれば。
Pythonのハッシュ可能オブジェクトを理解するための実用的な例を紹介しましょう。この例では2つのタプルを使用しています。タプルの各値には、その有効期間中に決して変更されない一意のハッシュ値があります。したがって、これには価値があります。2つのタプル間の比較が行われます。Id()を使用して、タプル要素のハッシュ値を取得できます。
Pythonでは、インデックスを返すためにオブジェクトをセットのメンバーにすることができます。つまり、一意のID / IDを持っています。
たとえば、Python 3.3では:
データ構造リストはハッシュ可能ではありませんが、データ構造タプルはハッシュ可能です。
id
、メモリ内のオブジェクトの(ほぼ)アドレスであるとは異なります。
Hashable =ハッシュ可能。
さて、ハッシュとは何ですか?ハッシュ関数は、オブジェクト、たとえば「Python」などの文字列を受け取り、固定サイズのコードを返す関数です。簡単にするために、戻り値は整数であると想定します。
Python 3でhash( 'Python')を実行すると、結果として5952713340227947791が返されます。異なるバージョンのPythonは、基礎となるハッシュ関数を自由に変更できるため、異なる値を取得する可能性があります。重要なことは、hash( 'Python')を何度も実行しても、同じバージョンのPythonで常に同じ結果が得られることです。
しかし、hash( 'Java')は1753925553814008565を返します。つまり、ハッシュしているオブジェクトが変化すると、結果も変化します。一方、ハッシュしているオブジェクトが変更されない場合、結果は同じままです。
なぜこれが問題なのですか?
たとえば、Python辞書では、キーが不変である必要があります。つまり、キーは変更されないオブジェクトでなければなりません。文字列は、他の基本的な型(int、float、bool)と同様に、Pythonでは不変です。タプルとfrozensetも不変です。一方、リストは変更できるため、不変ではありません(つまり、リストは変更可能です)。同様に、dictは変更可能です。
つまり、ハッシュ可能とは、不変であることを意味します。可変型をhash()関数に渡そうとすると失敗します。
>>> hash('Python')
1687380313081734297
>>> hash('Java')
1753925553814008565
>>>
>>> hash([1, 2])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> hash({1, 2})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'set'
>>> hash({1 : 2})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>>
>>> hash(frozenset({1, 2}))
-1834016341293975159
>>> hash((1, 2))
3713081631934410656
__hash__()
メソッドのドキュメントを参照してください。