演算子は変数の
is
値とは一致しませんが、インスタンス自体と一致します。
それは本当にどういう意味ですか?
x
名前を付けて両方の変数に同じ値を割り当てる2つの変数を宣言しましたが、演算子y
を使用するとfalseが返されます。is
説明が必要です。これが私のコードです。
x = [1, 2, 3]
y = [1, 2, 3]
print(x is y) # It prints false!
is
あなたはオペレーターが何をテストするかを誤解しました。2つの変数が同じ値を持っているかどうかではなく、2つの変数が同じオブジェクトを指しているかどうかをテストします。
is
オペレーター向けのドキュメントから:
演算子
is
とis not
オブジェクトIDのテスト:とが同じオブジェクトx is y
である場合にのみtrueになります。x
y
==
代わりに演算子を使用してください。
print(x == y)
これは印刷しTrue
ます。x
とy
は2つの別々のリストです。
x[0] = 4
print(y) # prints [1, 2, 3]
print(x == y) # prints False
id()
この関数を使用すると、それが表示されx
、y
さまざまな識別子が使用されます。
>>> id(x)
4401064560
>>> id(y)
4401098192
ただし、に割り当てる場合はy
、x
両方が同じオブジェクトを指します。
>>> x = y
>>> id(x)
4401064560
>>> id(y)
4401064560
>>> x is y
True
is
両方が同じオブジェクトであることを示し、を返しますTrue
。
Pythonでは、名前は値を参照する単なるラベルであることに注意してください。複数の名前で同じオブジェクトを指すようにすることができます。is
2つの名前が1つの同じオブジェクトを指しているかどうかを示します。==
2つの名前が同じ値を持つオブジェクトを参照しているかどうかを示します。
別の重複は、2つの等しい文字列が一般的に同一ではない理由を尋ねていましたが、ここでは実際には答えられていません。
>>> x = 'a'
>>> x += 'bc'
>>> y = 'abc'
>>> x == y
True
>>> x is y
False
では、なぜそれらは同じ文字列ではないのですか?特にこれを考えると:
>>> z = 'abc'
>>> w = 'abc'
>>> z is w
True
2番目の部分を少し延期しましょう。最初のものはどうして真実でしょうか?
インタプリタには、文字列値を文字列オブジェクトにマッピングするテーブルである「インターンテーブル」が必要になるため、内容を使用して新しい文字列を作成しようとするたびに'abc'
、同じオブジェクトが返されます。ウィキペディアには、インターンがどのように機能するかについてのより詳細な議論があります。
また、Pythonには文字列インターンテーブルがあります。このメソッドを使用して、文字列を手動でインターンできますsys.intern
。
実際、Pythonは不変の型を自動的にインターンすることができますが、そうする必要はありません。実装が異なれば、異なる値がインターンされます。
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
OK、でもなぜ同じだったz
の?w
これは、インタープリターが自動的にインターンするのではなく、コンパイラーのフォールディング値です。
同じコンパイル時の文字列が同じモジュールに2回表示される場合(これは正確に定義するのが難しいことを意味します。、、、はすべて異なるリテラルですが同じ文字列であるため、文字列リテラルと同じではありませんがr'abc'
、理解しやすいです。直感的に)、コンパイラは2つの参照を使用して文字列のインスタンスを1つだけ作成します。'abc'
'a' 'b' 'c'
実際、コンパイラーはさらに先に進むことができます。オプティマイザーによって'ab' + 'c'
変換できます。その場合、同じモジュール内の定数と'abc'
一緒に折りたたむことができます。'abc'
繰り返しますが、これはPythonで許可されているものですが、必須ではありません。ただし、この場合、CPythonは常に小さな文字列(および、たとえば小さなタプル)を折り畳みます。(ただし、対話型インタープリターのステートメントごとのコンパイラーは、module-at-a-timeコンパイラーと同じ最適化を実行しないため、対話式でまったく同じ結果が表示されることはありません。)
それで、あなたはプログラマーとしてこれについて何をすべきですか?
まあ…何も。2つの不変の値が同一であるかどうかを気にする理由はほとんどありません。a is b
の代わりにいつ使用できるかを知りたい場合a == b
は、間違った質問をしていることになります。a == b
次の2つの場合を除いて、常に使用してください。
x is None
。x
変更可能な値の場合、変更がに影響するかどうかを知る必要がある場合y
。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]
重複する質問によって促されると、このアナロジーは機能する可能性があります。
# - 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
is
とis 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
>>>
上記の例は、ID(Cpythonではメモリアドレスにすることもできます)がと(値が同じであっても)の両方a
で異なることを示しています。b
その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
>>>
上記の例では、a
とb
は2つの異なる変数ですが、がa is b
返されTrue
ます。これは、のタイプがa
不変int
オブジェクトであるためです。そのため、Python(メモリを節約すると思います)はb
、同じ値で作成されたときに同じオブジェクトを割り当てました。したがって、この場合、変数のIDは一致し、であるa is b
ことが判明しましたTrue
。
これは、すべての不変オブジェクトに適用されます。
>>> del a
>>> del b
>>> a = "asd"
>>> b = "asd"
>>> hex(id(a))
'0x1079b05a8'
>>> hex(id(b))
'0x1079b05a8'
>>> a is b
True
>>> a == b
True
>>>
お役に立てば幸いです。
x is y
と同じでid(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
参照;
https://docs.python.org/2/reference/expressions.html#is-not
https://docs.python.org/2/reference/expressions.html#id24
ここで小さな整数を確認できます。257を超える数値は小さな整数ではないため、別のオブジェクトとして計算されます。
==
この場合、代わりに使用することをお勧めします。
詳細については、こちらをご覧ください:http: //docs.python.org/2/c-api/int.html
Xは配列を指し、Yは別の配列を指します。これらの配列は同一ですが、is
オペレーターは同一ではないこれらのポインターを調べます。
オブジェクトID、つまり、変数がメモリ内の同じオブジェクトを参照しているかどうかを比較します。これは==
、JavaまたはCの場合と似ています(ポインターを比較する場合)。
果物の簡単な例
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 ) )
演算子は、のis
英語版に他なりません==
。2つのリストのIDが異なるため、答えは誤りです。あなたが試すことができます:
a=[1,2,3]
b=a
print(b is a )#True
*両方のリストのIDが同じになるため