is
オペレータは、変数の値が、インスタンス自身と一致していません。
それはどういう意味ですか?
2つの変数に名前x
をy
付けて宣言し、両方の変数に同じ値を割り当てましたが、is
演算子を使用するとfalseが返されます。
説明が必要です。これが私のコードです。
x = [1, 2, 3]
y = [1, 2, 3]
print(x is y) # It prints false!
is
オペレータは、変数の値が、インスタンス自身と一致していません。
それはどういう意味ですか?
2つの変数に名前x
をy
付けて宣言し、両方の変数に同じ値を割り当てましたが、is
演算子を使用するとfalseが返されます。
説明が必要です。これが私のコードです。
x = [1, 2, 3]
y = [1, 2, 3]
print(x is y) # It prints false!
回答:
is
オペレーターが何をテストするかを誤解しました。2つの変数が同じ値を持っているかどうかではなく、2つの変数が同じオブジェクトを指しているかどうかをテストします。
is
オペレーターのドキュメントから:
事業者
is
とis not
オブジェクトのアイデンティティのためのテストは:x is y
場合にのみ、真である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つの名前が同じ値を持つオブジェクトを参照しているかどうかを示します。
A is B
と同じid(A) == id(B)
です。
id(A)
、変数に格納せず、後で動作することvariable == id(B)
を期待している場合に限ります。A
その間に削除された場合B
、同じメモリ位置が与えられる可能性があります。
\n
>>> y = 5 \n
>>> x is y \n
True \n
>>> x == y \n
True \n
>>>\n
別の重複は、なぜ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'
、'abc'
と'a' 'b' 'c'
理解しやすい、すべての異なるリテラルが、同じ文字列が、しかし、直感的に)、コンパイラーは、2つの参照を持つ文字列のインスタンスを1つだけ作成します。
実際、コンパイラーはさらに先に進む'ab' + 'c'
ことができます。'abc'
オプティマイザーによって変換できます。その場合'abc'
、同じモジュール内の定数と一緒に折りたたむことができます。
繰り返しますが、これはPythonで許可されているものですが、必須ではありません。しかし、この場合、CPythonは常に小さな文字列(および、たとえば、小さなタプル)を折りたたみます。(ただし、対話型インタープリターのステートメントごとのコンパイラーは、モジュール単位のコンパイラーと同じ最適化を実行しないため、対話的に同じ結果が表示されることはありません。)
では、プログラマーとしてこれについて何をすべきでしょうか?
ええと…何も。2つの不変値が同一であるかどうかを気にする理由はほとんどありません。のa is b
代わりにいつ使用できるかを知りたいa == b
場合は、間違った質問をしています。次のa == b
2つの場合を除いて、常に使用します。
x is None
。x
がに影響するかどうかを知る必要がある場合y
。w
とz
理由値を折るコンパイラで同一であり、その理由であっても使用して、REPLでこのも作業を行いid()
参照をチェックしますか?Pythonの3.7でREPLを使用して
重複する質問によって促されて、この類推はうまくいくかもしれません:
# - 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つの識別演算子です。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
>>>
アイデンティティは(も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
IS 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
>>>
お役に立てば幸いです。
-5
よりも低い、または高いもの256
はすべてFalseになります。Pythonは[-5、256]の範囲の数値をキャッシュします。
x is y
id(x) == id(y)
オブジェクトのアイデンティティを比較すると同じです。
@ 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
オペレーターはそれらのポインターを調べますが、それらは同一ではありません。
is
オペレーターの機能はこれを示しています。
id
要求しない限り、一部のオブジェクトにはもありません。
果物の簡単な例
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 ) )