Python辞書はハッシュテーブルの例ですか?


187

Pythonの基本的なデータ構造の1つはディクショナリです。これにより、任意のタイプの「値」を検索するための「キー」を記録できます。これはハッシュテーブルとして内部的に実装されていますか?そうでない場合、それは何ですか?


2
技術的な詳細に興味がある場合は、Beautiful Codeの 1つの記事でPythonのdict実装の内部について説明しています。
Torsten Marek、

それは美しいコードで私のお気に入りの章の1つでした。
DGentry 2008

4
以下は、Brandon Craig Rhodesによる、python辞書の動作を説明するトークであるyoutube.com/watch?v=C4Kc8xzcA68です。
シャンドラ

しばらくの間、dictを表す図を探しました。これは、メモリとCPythonでの実装を示しています。本を参照していただきありがとうございます!
陳A.

回答:


239

はい、それはハッシュマッピングまたはハッシュテーブルです。Tim Petersが書いたpythonのdict実装の説明をここで読むことができます

そのため、リストのような「ハッシュ化できない」ものをdictキーとして使用することはできません。

>>> a = {}
>>> b = ['some', 'list']
>>> hash(b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list objects are unhashable
>>> a[b] = 'some'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list objects are unhashable

ハッシュテーブルの詳細読んだり、ハッシュテーブルがPythonにどのように実装されているか、またなぜそれがそのように実装されているのかを確認したりできます


1
ティムピーターズの縫い目が壊れるようにリンクしていますが、そこにはクリーンなリンクがありますか?
マット

1
@MattAlcock:リンクを更新しました。時々(通常、誰かが自分の電子メールアドレスをどこかに削除してもらいたいため)、Pythonリストアーカイブが再構築され、電子メールのIDが変更されるため、これらのリンクが壊れます。pydotorgの管理者は一般に、最近はそれを避けようとしています。
Martijn Pieters

ただし、を使用.keys()すると、キーのリストを取得できます。実際のハッシュテーブルは、キーを格納せず、領域を節約するためのハッシュを格納します。
noɥʇʎԀʎzɐɹƆ

python dict実装の詳細については、こちらをご覧ください:laurentluce.com/posts/python-dictionary-implementation
Daniel Goldfarb

32

Pythonディクショナリには、hash()でのテーブルルックアップ以上の機能が必要です。野蛮な実験により、私はこのハッシュの衝突を発見しました:

>>> hash(1.1)
2040142438
>>> hash(4504.1)
2040142438

それでも辞書を壊すことはありません:

>>> d = { 1.1: 'a', 4504.1: 'b' }
>>> d[1.1]
'a'
>>> d[4504.1]
'b'

サニティーチェック:

>>> for k,v in d.items(): print(hash(k))
2040142438
2040142438

おそらく、hash()の他に、辞書キー間の衝突を回避する別のルックアップレベルがあるでしょう。または、おそらくdict()は別のハッシュを使用します。

(ちなみに、これはPython 2.7.10で発生しhash(1.1) == hash(214748749.8)ます。Python3.4.3と3.5.0で同じ問題が発生し、衝突が発生します。)


14
衝突は避けられません。セットSには無数のアイテムが含まれている可能性があり、コンピューターが保存できる数にハッシュする必要があります。ハッシュテーブルのすべての使用可能な実装は、衝突を解決します。最も頻繁に見られる2つの方法は、a)オープンアドレス指定とb)チェーンです。完全なハッシュを使用していないからといって、ハッシュテーブルではないという意味ではありません。
TurnipEntropy 2017

1
可能な限り無限のハッシュ可能値と有限のハッシュコードがあるため、衝突は一般に起こります。ハッシュテーブルでさえ、なんとかして衝突を処理する必要があります。
Yanfeng Liu

3
@YanfengLiuそれらはTurnipEntropyが作ったのとまったく同じ点だと思います。
ボブスタイン

1
Python 3.7では、実際には2E20-1の可能なハッシュ値があるように見えます。-1E20マイナス1から(+)1E20マイナス1まで。hash('I wandered lonely as a cloud, that drifts on high o\'er vales and hills, when all at once, I saw a crowd, a host of golden daffodils.')これは19桁の10進数-4037225020714749784を示します。あなた自身の言葉で続けてください、子供たち、そしてハッシュはまだ19桁の数字です。Pythonではハッシュできる文字列の長さに制限があると思いますが、可能な値よりも多くの可能な文字列を言っても安全です。そして、hash(False)道による= 0。
Will Croxford


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.