Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonの関数がハッシュ可能な理由とその仕組みを徹底解説

ハッシュ可能(hashable)とは何か?

オブジェクトが「ハッシュ可能」であるとは、その生存期間中にハッシュ値が変化しないことを意味します。具体的には、__hash__() メソッドを持っていることに加えて、他のオブジェクトとの比較が可能である必要があります。この比較には __eq__() または __cmp__() メソッドが用いられます。

重要なルールとして、比較した結果「等しい」と判定されたハッシュ可能なオブジェクト同士は、必ず同じハッシュ値を持たなければなりません。

ハッシュ可能性が重要な理由

ハッシュ可能であることは、そのオブジェクトを辞書(dict)のキーや集合(set)の要素として利用できることを意味します。これらのデータ構造は内部的にハッシュ値を使って要素を高速に管理しているためです。

組み込みオブジェクトとハッシュ可能性

Python の組み込みオブジェクトのうち、すべてのイミュータブル(変更不可)なオブジェクトはハッシュ可能です。一方で、リストや辞書のようなミュータブル(変更可能)なコンテナはハッシュ不可能ですが、イミュータブルなコンテナであるタプルはハッシュ可能です。

ユーザー定義クラスのインスタンス

ユーザー定義クラスのインスタンスは、デフォルトでハッシュ可能になっています。これらのインスタンスは自分自身以外のオブジェクトとは等しくならず、そのハッシュ値は id() から導出されます。

lambda 関数のハッシュ値を確認する

ここで注意したいのは、ハッシュ値は必ずしも関数の ID と一致するわけではないという点です。次の lambda 関数の例を見てみましょう。

m = lambda x: 1
print(hash(m))
print(id(m))
print(m.__hash__())

実行結果:

1265925722
3074942372
1265925722

hash(m)m.__hash__() の戻り値は一致していますが、id(m) の値とは異なることが分かります。この結果から、lambda 関数もハッシュ可能であることが確認できます。

通常の関数もハッシュ可能

続いて、通常の関数 f() を定義して同じことを確認してみます。

def f(): pass
print(type(f))
print(f.__hash__())
print(hash(f))

実行結果:

<class 'function'>
1265925978
1265925978

このように、関数は生存期間中ずっと同じハッシュ値を持つため、あらゆる関数がハッシュ可能であると言えます。この性質のおかげで、関数を辞書のキーとして登録したり、集合に追加したりすることも可能になります。

  1. ハッシュ関数とハッシュテーブルの基本を徹底解説!代表的な3つの手法とは

    ハッシュ化(ハッシング)とは、ハッシュ関数と呼ばれる数学的な関数を用いて、テキストや数値のリストから値を生成する処理のことです。数値キーや英数字キーを扱うハッシュ関数は数多く存在し、それぞれ計算方法や特性が異なります。本記事では、代表的なハッシュ関数である「除算法」「乗算法」「中央二乗法」の仕組みと計算例を解説し、あわせてそれらを活用するデータ構造「ハッシュテーブル」についても詳しく紹介します。 ハッシュ関数とは ハッシュ関数は、任意のキー(データ)を受け取り、固定範囲内の数値(ハッシュ値)へ変換する関数です。以下に、代表的なハッシュ関数を3つ紹介します。 1. 除算法(デビジョン法) 除

  2. Pythonで関数から別の関数を返す方法をわかりやすく解説

    Pythonは第一級関数(first-class functions)をサポートしているプログラミング言語です。実際、Pythonにおけるすべての関数は第一級オブジェクトとして扱われます。 これは何を意味するのでしょうか。具体的には、以下のようなことが可能になります。 関数の中から別の関数を返す(returnする) 関数をリストや辞書などのコレクションに格納する 関数を、通常の変数やオブジェクトと同じように扱う さらに、関数の中で別の関数を定義し、それを返すことさえできます。これはクロージャ(closure)と呼ばれる強力なテクニックの基礎にもなる概念です。 サンプルコード:関数内で関数を