短い答えは次のとおりです。いいえ、そうではありません。リンク先のドキュメントには次のように書かれています。
オブジェクト IDの演算子is
とテスト: は、とが同じオブジェクトである場合にのみ真になります。is not
x is y
x
y
「同じオブジェクト」であることは、オーバーライドできるものではありません。オブジェクトが別のオブジェクトと同じでない場合、そのふりをすることはできません。
なぜ?is
and/orをオーバーライドさせることの害は何id
ですか? 明らかに、ほとんどの場合、それはばかげたことですが、Python では、十分に努力すれば、多くのばかげたことを実行できます。
設計 FAQ および同様のドキュメントには記載されていません。しかし、それは主に、Python やいくつかのより深い標準ライブラリ モジュールのデバッグが容易になるためだと思います。インタプリタ内から、2 つの名前が実際に同じオブジェクトを参照していることを確認したり、出力したりする方法があることを知っているからです。id
名前が時間の経過とともに変更されていないことを確認するためなど。それなしでデバッグを想像してみてweakref
くださいpickle
。
では、「同じオブジェクト」とは正確には何を意味するのでしょうか。まあ、それは通訳次第です。明らかに、同じオブジェクトの 2 つのインスタンスを言語レベルで区別することは不可能である必要があり、おそらくインタープリター レベルでも同様です (特に、ほとんどのインタープリター実装にプラグインするための明確に定義された API があるため)。
主要な実装はすべて、下位レベルの ID の概念に従うことでこれを処理します。CPython はPyObject*
ポインターの値を比較し、Jython は Java 参照を同一性比較し、PyPy はis
objectspace オブジェクトに対して実行します…</p>
PyPy sourceを見る価値があります。これは、「x is y
iffx
とy
are the same object 」が両方の方向で真であることを必要とします。トップレベルの式は、適切なオブジェクト空間内のx is y
オブジェクトが何であれ、 true であり、として実装されている場合に trueです。したがって、レベル Nでは、レベル N-1 の場合と異なります。wx
wy
wy.is_(wx)
is_
wy is wx
x is y
y is x
これは、PyPy を使用して、より高いレベルでdunder メソッドにアタッチするだけで、オーバーライドis
可能なPython の方言を簡単に作成できることを意味します。しかし、同じことを行うより簡単な方法があります。is_
__is__
def is_(x, y):
if hasattr(x, '__is__'):
return x.__is__(y)
elif hasattr(y, '__is__'):
return y.__is__(x)
else:
return x is y
今度はis_(x, y)
の代わりに をx is y
試してみて、インタープリターを変更するという大変な作業を行う前に (この場合はそれほど難しくなくても) 楽しいトラブルを見つけられるかどうかを確認してください。
それで、何is
と関係がありid
ますか?is
の上に実装できますid
—たとえば、x is y
チェックだけid(x) == id(y)
ですか? さて、id
:
オブジェクトの「アイデンティティ」を返します。これは、このオブジェクトの有効期間中に一意で一定であることが保証されている整数です。有効期間が重複しない 2 つのオブジェクトは、同じid()
値を持つ場合があります。
つまり、id
オブジェクトの は一意であり、その存続期間中一定であり、x is y
それらが同じオブジェクトである場合は true です。したがって、x is y
iff は trueid(x) == id(y)
ですよね?
まあ、id
あなたが望むものにリバウンドすることができますが、それは に影響を与えることはできませんis
. 定義を非常に慎重に作成した場合 ( へのbuiltins
参照を破棄するとid
、以前存在していた実装がもはや存在すること、または存在する場合に正しく動作することが保証されないことを覚えておいてください…)、上に定義することができis
ます。のデフォルト実装のid
。
しかし、それは奇妙なことです。CPython では、id(x)
「メモリ内のオブジェクトのアドレスを返す」だけで、メモリ内のオブジェクトへのポインタの値と同じです。しかし、これは CPython の成果物にすぎません。他の実装がid
、ID 比較に使用される基になる値を整数として返さなければならないということは何もありません。実際、(整数にキャストできる) ポインターを持たない言語で記述された実装でそれを行う方法は明らかではありません。PyPy では、id
オブジェクトの は、最初にアクセスされたときに計算された値であり、オブジェクト自体によってキー付けされた、オブジェクト空間の辞書に格納されている場合もあります。
に関して__hash__
は、ドキュメントの重要な部分を読み違えています。
[...] をx.__hash__()
返しますid(x)
。
省略した部分は、これがユーザー定義クラスのインスタンス (再定義しない) にのみ当てはまることを明確にしています__hash__
。たとえば、tuple
. 要するに、ID はハッシュとは何の関係もありませんが、一部のオブジェクトでは ID が便利なハッシュ値になるという点が異なります。