短い答えは:いいえ、そうではありません。
オブジェクト識別のための事業者is
とis not
テストを:あなたが言うにリンクドキュメントとしてx is y
はx
とy
が同じオブジェクトである場合にのみ当てはまります。
「同じオブジェクト」とは、あなたが上書きできるものではありません。あなたのオブジェクトが別のオブジェクトと同じオブジェクトでない場合、そのオブジェクトはふりをすることができません。
だから...なぜ? is
および/またはid
を無効にすることの害は何ですか?明らかに、これはほとんど常に愚かなことですが、Pythonでは十分な努力をすると多くの愚かなことができます。
デザインに関するよくある質問とそれに類する書類には言及していません。しかし、私はそれが主に、Pythonとより深い標準ライブラリモジュールのデバッグを容易にしていると考えています。インタープリタ内から、2つの名前が実際に同じオブジェクトを参照しているかどうかを確認する方法や、 id
は時間の経過とともに名前が変更されていないことを確認します。weakref
、またはそれ以外の場合はpickle
のデバッグを想像してください。
「同じオブジェクト」とはどういう意味ですか?さて、それは通訳者の責任です。明らかに、同じオブジェクトの2つのインスタンスを言語レベルで、おそらくインタープリタレベルでも区別することは不可能でなければなりません(ほとんどのインタープリタ実装にプラグインするための明確なAPIがあるため)。
すべての主な実装では、下位レベルのアイデンティティーの概念に従うことでこれを処理します。 CPythonのはPyObject*
ポインタの値を比較し、Jythonのは、アイデンティティ・比較Javaの参照を、PyPyは、オブジェクト・スペースのオブジェクトに関するis
...
それは価値があるが必要ですPyPy source、見てを行う「x
IFF x is y
とy
は同じオブジェクトであります"双方向で真実であること。適切なオブジェクト空間内の任意のオブジェクトwx
およびwy
が、wy.is_(wx)
が真であり、is_
がwy is wx
として実装されている場合、トップレベル式x is y
は真です。従ってレベルNにx is y
がある場合、レベルN-1でy is x
となる。
これは、あなたはかなり簡単にis
がただより高いレベルでdunder方法__is__
にis_
を装着することにより、無効にすることができるのPythonの方言を構築するためにPyPyを使用することを意味していることに注意してください。しかし、同じことを行うための簡単な方法があります:
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
は今、「それがにISN場合でも(is_(x, y)
の代わりx is y
と遊ぶ、そしてあなたが通訳を変更するハードワークを行う前に、すべての楽しトラブルを見つけることができるかどうかを確認しますこの場合ハード)。
ので、is
はid
とどんな関係があるのか。 is
はid
の上に実装できます。x is y
はちょうどid(x) == id(y)
をチェックしますか?まあ、id
:
オブジェクトの「同一性」を返します。これは、そのオブジェクトの存続期間中に一意で定数であることが保証されている整数です。寿命が重複しない2つのオブジェクトの値は同じid()
になる場合があります。
ので、オブジェクトのid
は、その存続期間中にユニークかつ一定であり、それらが同じオブジェクトだ場合に限っx is y
が真である、したがって、x is y
は右、真IFF id(x) == id(y)
のですか?
まあ、id
は、あなたが望むものにリバウンドすることができ、それはis
に影響しません。この定義を非常に慎重に作成した場合は、id
への参照を破棄した場合は、それ以上存在することが保証されていない場合でも、存在する場合は正常に動作することも保証されません...)、id
の既定の実装の上にis
を定義します。
しかし、それは奇妙なことです。 CPythonでは、id(x)
は「メモリ内のオブジェクトのアドレスを返す」だけです。メモリ内のオブジェクトへのポインタの値と同じものです。しかし、これは単なるCPythonの成果物です。 id
は、ID比較に使用される基になる値を整数として返さなければならないということは他にもありません。実際には、ポインターなしで(整数にキャストできる)言語で書かれたインプリメンテーションでそれをどうやって行うのかは明らかではありません。 PyPyでは、オブジェクトのid
は、最初にアクセスされたときに計算された値であってもよいし、オブジェクト自体のキーによってオブジェクト空間の辞書に隠されていてもよい。 __hash__
については
、あなたは、ドキュメントの重要な部分を誤読しています。
[...] x.__hash__()
はid(x)
を返します。
省略された部分は、ユーザー定義クラスのインスタンス(__hash__
を再定義しない場合)にのみ当てはまることが明らかです。明らかに、たとえばtuple
の場合は当てはまりません。要するに、アイデンティティはハッシュとは関係がありませんが、一部のオブジェクトではアイデンティティが便利なハッシュ値になります。
あなたの例は実際には面白いです。 Favourited that :) – nneonneo
デフォルトの 'hash'の定義は正しくありません。 CPythonでは、 'PyBaseObject_Type.tp_hash'は' long _Py_HashPointer(void * p){long x;}です。 size_t y =(size_t)p; y =(y >> 4)| (y <<(8 * SIZEOF_VOID_P-4)); x =(long)y; if(x == -1)x = -2; return x;} 'これは、アドレスの下位2〜4ビットがおそらく0である場合、ハッシュ衝突を減らすためにアドレスを4ビット回転させます。 – eryksun