web-dev-qa-db-ja.com

ハッシュはPythonで何をしますか?

hash関数がTupleに適用されるコードの例をみました。結果として、負の整数を返します。この機能は何をするのだろうか。 Googleは役に立ちません。ハッシュの計算方法を説明するページを見つけましたが、この関数が必要な理由は説明していません。

61
Roman

ハッシュは特定の値を識別する固定サイズの整数です 。各値には独自のハッシュが必要であるため、同じ値では、同じオブジェクトでなくても同じハッシュを取得できます。

>>> hash("Look at me!")
4343814758193556824
>>> f = "Look at me!"
>>> hash(f)
4343814758193556824

ハッシュ値は、結果の値が均等に分布して、発生するハッシュ衝突の数を減らすように作成する必要があります。ハッシュ衝突は、2つの異なる値が同じハッシュを持つ場合です。したがって、比較的小さな変更では、非常に異なるハッシュが頻繁に発生します。

>>> hash("Look at me!!")
6941904779894686356

これらの数値は、大量の値のコレクションで値をすばやく検索できるため、非常に便利です。それらの使用の2つの例は、Pythonのsetdictです。 listで、値がリストにあるかどうかを確認したい場合、if x in values:で、Pythonはリスト全体を調べてxと比較する必要がありますリスト内の各値values。これには、長いlist時間がかかります。 setでは、Pythonは各ハッシュを追跡し、if x in values:と入力すると、Pythonはxのハッシュ値を取得します、内部構造を調べ、xと同じハッシュを持つ値とのみxを比較します。

辞書の検索にも同じ方法が使用されます。これにより、setおよびdictでのルックアップが非常に高速になり、listでのルックアップが遅くなります。また、listにはハッシュ不可のオブジェクトを含めることができますが、setには、またはdictのキーとしては使用できません。ハッシュ不可能なオブジェクトの典型的な例は、可変のオブジェクトです。つまり、値を変更できます。可変オブジェクトがある場合、ハッシュは有効期間内に変更されるため、ハッシュ可能ではなりません。これは、オブジェクトがディクショナリ内の間違ったハッシュ値で終わる可能性があるため、多くの混乱を引き起こします。

値のハッシュは、Pythonの1回の実行に対してのみ同じである必要があることに注意してください。 Python 3.3では、実際にPythonを実行するたびに変更されます。

$ /opt/python33/bin/python3
Python 3.3.2 (default, Jun 17 2013, 17:49:21) 
[GCC 4.6.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> hash("foo")
1849024199686380661
>>> 
$ /opt/python33/bin/python3
Python 3.3.2 (default, Jun 17 2013, 17:49:21) 
[GCC 4.6.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> hash("foo")
-7416743951976404299

これは、特定の文字列がどのハッシュ値を持つかを推測するのを難しくすることです。これは、Webアプリケーションなどの重要なセキュリティ機能です。

したがって、ハッシュ値を永続的に保存しないでください。ハッシュ値を永続的な方法で使用する必要がある場合は、ファイルの検証可能なチェックサムを作成するために使用できる、より「深刻な」タイプのハッシュ cryptographic hash functions を確認できます。

108
Lennart Regebro

TL; DR:

用語集 を参照してください:hash()は、オブジェクトを比較するためのショートカットとして使用されます。オブジェクトは、他のオブジェクトと比較できる場合、ハッシュ可能と見なされます。それがhash()を使用する理由です。また、 CPythonのサイズ変更可能なハッシュテーブル として実装されるdictおよびset要素へのアクセスにも使用されます。

技術的な考慮事項

  • 通常、オブジェクトの比較(複数レベルの再帰が含まれる場合があります)は費用がかかります。
  • hash()関数は、1桁(または数個)安価であることが好ましい。
  • 2つのハッシュを比較することは、2つのオブジェクトを比較するよりも簡単です。ここがショートカットです。

辞書の実装方法 について読む場合、ハッシュテーブルを使用します。つまり、オブジェクトからキーを取得することは、O(1)の辞書でオブジェクトを取得するための礎石です。ただし、ハッシュ関数が衝突耐性であることに大きく依存しています。辞書の アイテムを取得する最悪のケース は、実際にはO(n)です。

そのメモでは、通常、可変オブジェクトはハッシュ可能ではありません。ハッシュ可能なプロパティは、オブジェクトをキーとして使用できることを意味します。ハッシュ値がキーとして使用され、その同じオブジェクトのコンテンツが変更された場合、ハッシュ関数は何を返しますか?同じキーですか、それとも異なるキーですか?それは、ハッシュ関数の定義方法に依存します

例による学習:

このクラスがあると想像してください:

>>> class Person(object):
...     def __init__(self, name, ssn, address):
...         self.name = name
...         self.ssn = ssn
...         self.address = address
...     def __hash__(self):
...         return hash(self.ssn)
...     def __eq__(self, other):
...         return self.ssn == other.ssn
... 

注:これはすべて、SSNが個人に対して決して変化しないという仮定に基づいています(信頼できるソースからその事実を実際に検証する場所さえ知らない)。

そしてボブがいます:

>>> bob = Person('bob', '1111-222-333', None)

ボブは名前を変えるために裁判官に会いに行きます:

>>> jim = Person('jim bo', '1111-222-333', 'sf bay area')

これは私たちが知っていることです:

>>> bob == jim
True

しかし、これらは、同じ人物の2つの異なるレコードのように、異なるメモリが割り当てられた2つの異なるオブジェクトです。

>>> bob is jim
False

Hash()が便利な部分になりました:

>>> dmv_appointments = {}
>>> dmv_appointments[bob] = 'tomorrow'

何だと思う:

>>> dmv_appointments[jim] #?
'tomorrow'

2つの異なるレコードから、同じ情報にアクセスできます。今これを試してください:

>>> dmv_appointments[hash(jim)]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 9, in __eq__
AttributeError: 'int' object has no attribute 'ssn'
>>> hash(jim) == hash(hash(jim))
True

今何があったの?それは衝突です。 hash(jim) == hash(hash(jim))はどちらも整数であるため、__getitem__の入力を、衝突するすべてのアイテムと比較する必要があります。組み込みのintにはssn属性がないため、トリップします。

>>> del Person.__eq__
>>> dmv_appointments[bob]
'tomorrow'
>>> dmv_appointments[jim]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: <__main__.Person object at 0x7f611bd37110>

この最後の例では、衝突があっても比較が実行され、オブジェクトが等しくなくなることを示しています。つまり、KeyErrorが正常に発生します。

25
dnozay

Python hash()のドキュメント 状態:

ハッシュ値は整数です。辞書検索時に辞書キーをすばやく比較するために使用されます。

Python辞書はハッシュテーブルとして実装されます。したがって、辞書を使用するときはいつでも、割り当てまたはルックアップのために渡したキーでhash()が呼び出されます。

さらに、 dictタイプのドキュメント 状態:

hashableではない値、つまり、リスト、辞書、または他の可変タイプを含む値(オブジェクトIDではなく値で比較される)は、キーとして使用されます。

2

ハッシュは辞書とセットで使用され、オブジェクトをすばやく検索します。良い出発点は、ウィキペディアの ハッシュテーブル に関する記事です。

1
NPE

私も非常に長い間それを探していました、今、私はあなたのすべてとせん断するので私の答えを得ました...

PythonでDictionaryデータ型を使用してください。非常にsimileにthehash...また、ネストされたハッシュのネストされたハッシュに対応しています。

例:-

dict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}
dict['Age'] = 8; # update existing entry
dict['School'] = "DPS School" # Add new entry

print ("dict['Age']: ", dict['Age'])
print ("dict['School']: ", dict['School'])

辞書データ型: https://www.tutorialspoint.com/python3/python_dictionary.htm

問題を解決することを願っています。

0