web-dev-qa-db-ja.com

Pythonの「is」演算子を理解する

is演算子は変数の値ではなく、インスタンス自体と一致します。

それは本当にどういう意味ですか?

xyという2つの変数を宣言し、両方の変数に同じ値を割り当てましたが、is演算子を使用するとfalseを返します。

明確化が必要です。これが私のコードです。

x = [1, 2, 3]
y = [1, 2, 3]

print x is y #It prints false!
96

is演算子がテストするものを誤解しました。 2つの変数が同じ値を持つかどうかではなく、2つの変数が同じオブジェクトを指すかどうかをテストします。

is演算子 のドキュメントから:

演算子isおよびis notは、オブジェクトの同一性をテストします:xyが同じオブジェクトである場合にのみ、x is yはtrueです。

代わりに==演算子を使用してください:

print x == y

これはTrueを出力します。 xyは2つのseparateリストです。

x[0] = 4
print(y)  # prints [1, 2, 3]
print(x == y)   # prints False

id() function を使用すると、xyの識別子が異なることがわかります。

>>> id(x)
4401064560
>>> id(y)
4401098192

ただし、yxに割り当てる場合、両方とも同じオブジェクトを指します。

>>> x = y
>>> id(x)
4401064560
>>> id(y)
4401064560
>>> x is y
True

isは両方が同じオブジェクトであることを示し、Trueを返します。

Pythonでは、 名前は値を参照する単なるラベルです ;複数の名前が同じオブジェクトを指すようにすることができます。 isは、2つの名前が1つの同じオブジェクトを指しているかどうかを示します。 ==は、2つの名前が同じ値を持つオブジェクトを参照しているかどうかを示します。

161
Martijn Pieters

別の重複 は、2つの等しい文字列が一般的に同一ではない理由を尋ねていましたが、実際にはここでは答えられません:

>>> x = 'a' 
>>> x += 'bc'
>>> y = 'abc'
>>> x == y
True
>>> x is y
False

それで、なぜ彼らは同じ文字列ではないのですか?特にこれを考えると:

>>> z = 'abc'
>>> w = 'abc'
>>> z is w
True

2番目の部分を少し先送りしましょう。最初の1つはどうして本当でしょうか?

インタプリタには、文字列値を文字列オブジェクトにマッピングするテーブルである「インターンテーブル」が必要になるため、'abc'の内容で新しい文字列を作成しようとするたびに、同じオブジェクトが返されます。 Wikipedia には、インターンがどのように機能するかについての詳細な議論があります。

Pythonhas文字列インターンテーブル; sys.intern メソッドを使用して文字列を手動でインターンできます。

実際、Pythonはallowedであり、不変型を自動的にインターンできますが、requiredそうする。異なる実装は異なる値をインターンします。

CPython(使用している実装がわからない場合に使用している実装)は、小さな整数とFalseなどの特殊なシングルトンを自動インターンしますが、文字列(または大きな整数、小さなタプル、他に何か)。これはかなり簡単に見ることができます:

>>> a = 0
>>> a += 1
>>> b = 1
>>> a is b
True
>>> a = False
>>> a = not a
>>> b = True
a is b
True
>>> a = 1000
>>> a += 1
>>> b = 1001
>>> a is b
False

わかりましたが、なぜzwは同一でしたか?

インタープリターが自動的にインターンするのではなく、コンパイラーが値を折りたたみます。

同じモジュールに同じコンパイル時の文字列が2回現れる場合(正確にはこれが意味することは定義が困難です。r'abc''abc'、および'a' 'b' 'c'はすべて同じリテラルですが、文字列リテラルと同じではありませんが、直感的に理解しやすい)、コンパイラは2つの参照を使用して、文字列の1つのインスタンスのみを作成します。

実際、コンパイラーはさらに先へ進むことができます。'ab' + 'c'はオプティマイザーによって'abc'に変換できます。この場合、同じモジュール内の'abc'定数と一緒にフォールドできます。

繰り返しますが、これはPythonが許可されていますが、必須ではありません。ただしこの場合、CPythonは常に小さな文字列(および小さなタプルなど)を常に折りたたみます。 (インタラクティブインタープリターのステートメントごとのコンパイラーは、モジュールごとのコンパイラーと同じ最適化を実行しないため、まったく同じ結果がインタラクティブに表示されることはありません。)


それで、プログラマーとしてこれについてどうすればいいですか?

まあ…何もない。 2つの不変値が同一であるかどうかを気にする必要はほとんどありません。 a is bではなくa == bをいつ使用できるかを知りたい場合は、間違った質問をしていることになります。次の2つの場合を除いて、常にa == bを使用してください。

  • x is Noneなどのシングルトン値とのより読みやすい比較。
  • 可変値の場合、xの変更がyに影響するかどうかを知る必要がある場合。
52
abarnert

重複した質問 でプロンプトが表示された場合、この類推は機能する可能性があります。

# - Darling, I want some pudding!
# - There is some in the fridge.

pudding_to_eat = fridge_pudding
pudding_to_eat is fridge_pudding
# => True

# - Honey, what's with all the dirty dishes?
# - I wanted to eat pudding so I made some. Sorry about the mess, Darling.
# - But there was already some in the fridge.

pudding_to_eat = make_pudding(ingredients)
pudding_to_eat is fridge_pudding
# => False
7
Amadan

isは、実際に同じオブジェクトである場合にのみtrueを返します。それらが同じである場合、一方への変更は他方にも現れます。違いの例を次に示します。

>>> x = [1, 2, 3]
>>> y = [1, 2, 3]
>>> print x is y
False
>>> z = y
>>> print y is z
True
>>> print x is z
False
>>> y[0] = 5
>>> print z
[5, 2, 3]
7
Mark Ransom

isis notは、Pythonの2つのID演算子です。 is演算子は変数の値を比較しませんが、変数のIDを比較します。このことを考慮:

>>> a = [1,2,3]
>>> b = [1,2,3]
>>> hex(id(a))
'0x1079b1440'
>>> hex(id(b))
'0x107960878'
>>> a is b
False
>>> a == b
True
>>>

上記の例は、abの両方でID(Cpythonのメモリアドレスでも可)が異なることを示しています(値は同じでも)。 a is bと言うと、両方のオペランドのIDの不一致が原因でfalseを返します。ただし、a == bと言うと、==操作は両方のオペランドに同じ値が割り当てられているかどうかのみを検証するため、trueを返します。

興味深い例(追加グレードの場合):

>>> del a
>>> del b
>>> a = 132
>>> b = 132
>>> hex(id(a))
'0x7faa2b609738'
>>> hex(id(b))
'0x7faa2b609738'
>>> a is b
True
>>> a == b
True
>>>

上記の例では、abは2つの異なる変数ですが、a is bTrueを返しました。これは、aのタイプがintであり、不変オブジェクトであるためです。したがって、python(メモリを節約すると思います)は、同じ値で作成されたときに、同じオブジェクトをbに割り当てました。したがって、この場合、変数のIDが一致し、a is bTrueであることが判明しました。

これはすべての不変オブジェクトに適用されます:

>>> del a
>>> del b
>>> a = "asd"
>>> b = "asd"
>>> hex(id(a))
'0x1079b05a8'
>>> hex(id(b))
'0x1079b05a8'
>>> a is b
True
>>> a == b
True
>>>

それが役に立てば幸いです。

5
gixxer

ここでは小さな整数を確認できます。 257を超える数値は小さな整数ではないため、別のオブジェクトとして計算されます。

この場合は、代わりに==を使用することをお勧めします。

詳細はこちら: http://docs.python.org/2/c-api/int.html

3
CS Gamer

x is yid(x) == id(y)と同じで、オブジェクトのIDを比較します。

@ tomasz-kurganが以下のコメントで指摘したように、is演算子は特定のオブジェクトに対して異常に動作します。

例えば。

>>> class A(object):
...   def foo(self):
...     pass
... 
>>> a = A()
>>> a.foo is a.foo
False
>>> id(a.foo) == id(a.foo)
True

Ref;
https://docs.python.org/2/reference/expressions.html#is-not
https://docs.python.org/2/reference/expressions.html#id24

3
Nizam Mohamed

Xは配列を指し、Yは異なる配列を指します。これらの配列は同一ですが、is演算子は、同一ではないポインターを調べます。

2
Neko

オブジェクトの同一性、つまり変数がメモリ内の同じオブジェクトを参照しているかどうかを比較します。 JavaまたはCの==またはC(ポインターを比較する場合)に似ています。

1
mipadi

果物の簡単な例

fruitlist = [" Apple ", " banana ", " cherry ", " durian "]
newfruitlist = fruitlist
verynewfruitlist = fruitlist [:]
print ( fruitlist is newfruitlist )
print ( fruitlist is verynewfruitlist )
print ( newfruitlist is verynewfruitlist )

出力:

True
False
False

しようとしたら

fruitlist = [" Apple ", " banana ", " cherry ", " durian "]
newfruitlist = fruitlist
verynewfruitlist = fruitlist [:]
print ( fruitlist == newfruitlist )
print ( fruitlist == verynewfruitlist )
print ( newfruitlist == verynewfruitlist )

出力は異なります。

True
True
True

これは、==演算子が変数の内容のみを比較するためです。 2変数のIDを比較するには、is演算子を使用します

識別番号を印刷するには:

print ( id( variable ) )
1
ForsakenOne