ホームページ  >  記事  >  バックエンド開発  >  Pythonで出てくるisとidとは何ですか?

Pythonで出てくるisとidとは何ですか?

巴扎黑
巴扎黑オリジナル
2017-04-30 16:28:491918ブラウズ

(ob1 は ob2) は (id(ob1) == id(ob2)) と同等です

まず、id 関数はオブジェクトのメモリ アドレスを取得できます。2 つのオブジェクトのメモリ アドレスが同じである場合、2 つのオブジェクトは 1 つのオブジェクトである必要があります。はと同等です。証拠としての Python ソースコード。

りー

しかし、以下のコードでこの状況がどのように発生するかを見てください。

りー

2 つのオブジェクトは is を使用すると False と判断されますが、id を使用すると True と判断されます。これは私たちが知っている事実と矛盾します。この現象をどう説明しますか。この状況に対する最善の解決策は、dis モジュールを呼び出して 2 つの比較ステートメントが何を行うかを確認することです。

りー

実際の状況は、 . 演算子が実行されると、実際にはプロキシ オブジェクトが生成されます。 foo.bar が Foo.bar の場合、スタック上で 2 つのオブジェクトが生成され、アドレスが異なるため、False になる必要があります。ただし、 id(foo.bar) == id(Foo.bar) の場合は異なります。まず、foo.bar が生成され、その後、foo.bar のアドレスが計算されます。オブジェクトが foo を指しているため、foo.bar オブジェクトが解放されます。次に、Foo.bar オブジェクトを生成します。 foo.bar と Foo.bar は同じメモリ サイズを占有するため、元の foo.bar のメモリ アドレスが再利用されるため、 id(foo.bar) == id(Foo.bar )は真です。

以下の内容は、Leo Jay によって電子メールで提供され、より明確に説明されています。

id(式 a) == id(式 b) を使用して 2 つの式の結果が同じオブジェクトであるかどうかを判断するという考えには問題があります。

foo.bar のこの形式は属性参照 [1] と呼ばれ、式の一種です。 foo はインスタンスオブジェクト、bar はメソッドです。このとき、式 foo.bar によって返される結果をメソッドオブジェクトと呼びます [2]。ドキュメントによると:

りー

foo.bar 自体は単純な名前ではなく、メソッド オブジェクトである式の計算結果です。id(foo.bar) などの式では、メソッド オブジェクトは単なる一時的な中間変数です。変数を ID として使用します。

よりわかりやすい例は、

static PyObject *
 cmp_outcome(int op, register PyObject *v, register PyObject *w)
{
 int res = 0;
 switch (op) {
 case PyCmp_IS:
  res = (v == w);
 break;
 case PyCmp_IS_NOT:
res = (v != w);
 break;

です。 出力結果もTrue

id[3] のドキュメントを見てください:

りー

オブジェクトが破棄されないことが保証できる場合にのみ、ID を使用して 2 つのオブジェクトを比較できます。したがって、比較する必要がある場合は、次のように書く必要があります:

In [1]: def bar(self, x):
...:     return self.x + y
...: 

In [2]: class Foo(object):
...:     x = 9
...:     def __init__(self ,x):
...:         self.x = x
...:     bar = bar
...:     

In [3]: foo = Foo(5)

In [4]: foo.bar is Foo.bar
Out[4]: False

In [5]: id(foo.bar) == id(Foo.bar)
Out[5]: True

つまり、2 つの式の結果を名前にバインドし、それらが同じオブジェクトであるかどうかを比較することで、正しい結果を得ることができます。

is 式 [4] にも同じことが当てはまります。現在得られる正しい結果は、完全に CPython の現在の実装の詳細によるものです。現在の is の実装では、左側と右側のオブジェクトを計算し、2 つのオブジェクトのアドレスが同じかどうかを比較します。いつか変更した場合は、まず左辺を計算してアドレスを保存し、左辺を解放してから右辺を計算し、再度比較すると結果が間違っている可能性があります。この問題は公式ドキュメント [5] にも記載されています。正しい方法は id のように、まず左辺と右辺を計算し、それぞれの名前に明示的にバインドしてから is を使用して判断する方法だと思います。

[1] http://docs.python.org/2/reference/expressions.html#attribute-references
[2] http://docs.python.org/2/tutorial/classes.html#method-objects
[3] http://docs.python.org/2/library/functions.html#id
[4] http://docs.python.org/2/reference/expressions.html#index-68
[5] http://docs.python.org/2/reference/expressions.html#id26

以上がPythonで出てくるisとidとは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。