「==」と「である」に違いはありますか?
質問
私の Google-fu 私は失敗しました。
Python では、次の 2 つの等価性テストは同等ですか?
n = 5
# Test one.
if n == 5:
print 'Yay!'
# Test two.
if n is 5:
print 'Yay!'
これは、インスタンスを比較するオブジェクトにも当てはまりますか ( list
言う)?
さて、私の質問に対する答えは次のとおりです。
L = []
L.append(1)
if L == [1]:
print 'Yay!'
# Holds true, but...
if L is [1]:
print 'Yay!'
# Doesn't.
それで ==
値をテストします。 is
それらが同じオブジェクトであるかどうかをテストしますか?
解決
is
戻ります True
2 つの変数が同じオブジェクトを指している場合、 ==
変数によって参照されるオブジェクトが等しい場合。
>>> a = [1, 2, 3]
>>> b = a
>>> b is a
True
>>> b == a
True
>>> b = a[:] # Make a new copy of list `a` via the slice operator, and assign it to variable `b`
>>> b is a
False
>>> b == a
True
あなたの場合、Python が小さな整数オブジェクトをキャッシュするため、2 番目のテストのみが機能します。これは実装の詳細です。より大きな整数の場合、これは機能しません。
>>> 1000 is 10**3
False
>>> 1000 == 10**3
True
文字列リテラルにも同じことが当てはまります。
>>> "a" is "a"
True
>>> "aa" is "a" * 2
True
>>> x = "a"
>>> "aa" is x * 2
False
>>> "aa" is intern(x*2)
True
参照してください この質問 同じように。
他のヒント
いつ使用するかを示す簡単な経験則があります。 ==
または is
.
==
のためです 価値の平等. 。2 つのオブジェクトが同じ値を持つかどうかを知りたい場合に使用します。is
のためです 参照の等価性. 。2 つの参照が同じオブジェクトを参照しているかどうかを知りたい場合に使用します。
一般に、何かを単純な型と比較するときは、通常、次のことをチェックします。 価値の平等, 、したがって、使用する必要があります ==
. 。たとえば、この例の目的は、おそらく x の値が 2 に等しいかどうかを確認することです (==
)、どうかではありません x
は文字通り 2 と同じオブジェクトを指します。
他に注意すべき点:CPython リファレンス実装の仕組みのため、誤って使用すると予期しない一貫性のない結果が得られます。 is
整数の参照の等価性を比較するには:
>>> a = 500
>>> b = 500
>>> a == b
True
>>> a is b
False
それはほぼ私たちが予想していた通りです: a
そして b
同じ値を持ちますが、別個のエンティティです。しかし、これはどうでしょうか?
>>> c = 200
>>> d = 200
>>> c == d
True
>>> c is d
True
これは以前の結果と矛盾します。何が起きてる?Python のリファレンス実装では、パフォーマンス上の理由から、-5..256 の範囲の整数オブジェクトをシングルトン インスタンスとしてキャッシュしていることがわかりました。これを示す例を次に示します。
>>> for i in range(250, 260): a = i; print "%i: %s" % (i, a is int(str(i)));
...
250: True
251: True
252: True
253: True
254: True
255: True
256: True
257: False
258: False
259: False
これも使用しない明らかな理由です is
:値の等価性を誤って使用した場合、動作は実装に任されます。
==
値が等しいかどうかを判断します。 is
それらがまったく同じオブジェクトであり等しいかどうかを判断します。
違いはありますか
==
そしてis
Pythonで?
はい、それらには非常に重要な違いがあります。
==
:等しいかどうかを確認する - セマンティクスでは、同等のオブジェクト (必ずしも同じオブジェクトである必要はない) が等しいかどうかをテストします。として ドキュメントによると:
演算子 <、>、==、>=、<=、および != は、2 つのオブジェクトの値を比較します。
is
:ID のチェック - セマンティクスは、オブジェクト (メモリ内に保持されているもの) であることを意味します。 は オブジェクト。繰り返しになりますが、 ドキュメントによると:
オペレーター
is
そしてis not
オブジェクトのアイデンティティをテストします。x is y
場合にのみ真実ですx
そしてy
は同じオブジェクトです。オブジェクトのアイデンティティは、を使用して決定されますid()
関数。x is not y
逆真実の値を生み出します。
したがって、同一性のチェックは、オブジェクトの ID の同一性のチェックと同じです。あれは、
a is b
は次と同じです:
id(a) == id(b)
どこ id
「同時に存在するオブジェクト間で一意であることが保証される」整数を返す組み込み関数です (「同時に存在するオブジェクト間で一意であることが保証されている」整数を返します)。 help(id)
) そして、どこ a
そして b
任意のオブジェクトです。
その他の使用方法
これらの比較は、セマンティクスのために使用する必要があります。使用 is
身元を確認するためと、 ==
平等性を確認するため。
標準ライブラリの公式 Python スタイル ガイドである PEP 8 にも言及されています。 の 2 つのユースケース is
:
のようなシングルトンとの比較
None
常に行う必要がありますis
またはis not
, 、決して等価演算子ではありません。また、書き込みには注意してください
if x
本当にそう思っているときif x is not None
- 例:変数または引数がデフォルトであるかどうかをテストするときNone
他の値に設定されました。もう1つの値には、ブールのコンテキストで偽である可能性のあるタイプ(コンテナなど)がある場合があります。
同一性から等価性を推測する
もし is
それは真実です、平等は可能です いつもの 推論される - 論理的に、オブジェクトがそれ自体である場合、それはそれ自体と同等であるかどうかをテストする必要があります。
ほとんどの場合、このロジックは当てはまりますが、それは __eq__
特別な方法。として ドキュメント 言う、
等価比較のデフォルトの動作 (
==
そして!=
)オブジェクトのアイデンティティに基づいています。したがって、同じアイデンティティと同じアイデンティティを持つインスタンスの平等比較により、平等が発生し、異なるアイデンティティを持つインスタンスの平等比較は不平等になります。このデフォルトの動作の動機は、すべてのオブジェクトが再帰的であることを望んでいることです(つまり、x が y は x == y を意味します)。
一貫性を保つために、次のことを推奨します。
等価比較は再帰的に行う必要があります。言い換えれば、同一のオブジェクトは等しいと比較する必要があります。
x is y
暗示するx == y
これがカスタム オブジェクトのデフォルトの動作であることがわかります。
>>> class Object(object): pass
>>> obj = Object()
>>> obj2 = Object()
>>> obj == obj, obj is obj
(True, True)
>>> obj == obj2, obj is obj2
(False, False)
対偶も通常は真です。何かが等しくないとテストされた場合、通常、それらは同じオブジェクトではないと推測できます。
同等性のテストはカスタマイズできるため、この推論はすべての型に常に当てはまるわけではありません。
例外
注目すべき例外は、 nan
- 常にそれ自体と等しくないことをテストします。
>>> nan = float('nan')
>>> nan
nan
>>> nan is nan
True
>>> nan == nan # !!!!!
False
同一性のチェックは、等価性のチェック (メンバーの再帰的なチェックが必要になる場合があります) よりもはるかに高速なチェックです。
ただし、複数のオブジェクトが同等であることが判明する場合、これを同等性の代わりに使用することはできません。
リストとタプルの等価性の比較では、オブジェクトの同一性が等しいと想定されることに注意してください (これは高速チェックであるため)。これは、ロジックに一貫性がない場合に矛盾が生じる可能性があります。 nan
:
>>> [nan] == [nan]
True
>>> (nan,) == (nan,)
True
注意すべき話:
質問は使用しようとしています is
整数を比較します。整数のインスタンスが、別の参照によって取得されたインスタンスと同じであると想定すべきではありません。この話はその理由を説明します。
コメント投稿者は、Python では等しいかどうかをチェックするのではなく、小さな整数 (-5 から 256 まで) がシングルトンであるという事実に依存するコードを作成していました。
うわー、これは潜伏性のバグにつながる可能性があります。a が b であるかどうかをチェックするコードがありましたが、a と b は一般に小さい数値であるため、希望どおりに機能しました。このバグは、運用開始から 6 か月後の今日にのみ発生しました。 a と b が最終的にキャッシュされないほど大きくなったためです。– GWG
開発ではうまくいきました。いくつかの単体テストに合格している可能性があります。
そして、それは実稼働環境でも機能しましたが、コードが 256 より大きい整数をチェックするまでは機能していましたが、その時点で実稼働環境では失敗しました。
これは、コード レビューまたはスタイル チェッカーで検出された可能性のある運用上の失敗です。
強調しておきます。 使ってはいけません is
整数を比較します。
違いは何ですか is
そして ==
?
==
そして is
比較が違います!他の人がすでに言ったように:
==
オブジェクトの値を比較します。is
オブジェクトの参照を比較します。
Python では、名前はオブジェクトを指します。たとえば、この場合 value1
そして value2
を参照してください int
値を格納するインスタンス 1000
:
value1 = 1000
value2 = value1
なぜなら value2
同じオブジェクトを指します is
そして ==
あげる True
:
>>> value1 == value2
True
>>> value1 is value2
True
次の例では、名前は value1
そして value2
別のものを参照する int
両方のインスタンスに同じ整数が格納されている場合でも、次のようになります。
>>> value1 = 1000
>>> value2 = 1000
同じ値(整数)が格納されているため ==
になるだろう True
, 、そのため、「値の比較」と呼ばれることがよくあります。しかし is
戻ります False
これらは異なるオブジェクトであるため、
>>> value1 == value2
True
>>> value1 is value2
False
いつどれを使うべきですか?
一般的に is
比較ははるかに高速です。それが、CPython がキャッシュ (またはおそらく 再利用する の方が適切な用語です) 小さな整数や文字列などの特定のオブジェクト。しかし、これは次のように扱う必要があります 実装の詳細 それは、(可能性は低いとしても)警告なしにいつでも変更される可能性があります。
あなたがすべき 使うだけ is
もし、あんたが:
- 2 つのオブジェクトが本当に同じオブジェクト (単に同じ「値」というだけではない) であるかどうかを確認したい。一例として次のようなことが考えられます。 あなた シングルトンオブジェクトを定数として使用します。
値をと比較したい パイソン 絶え間ない. 。Python の定数は次のとおりです。
None
True
1False
1NotImplemented
Ellipsis
__debug__
- クラス (たとえば、
int is int
またはint is float
) - 組み込みモジュールまたはサードパーティ モジュールには追加の定数が存在する可能性があります。例えば
np.ma.masked
NumPy モジュールから)
で 他のすべての場合に使用する必要があります ==
等しいかどうかを確認します。
動作をカスタマイズできますか?
という側面もある ==
それは他の回答ではまだ言及されていません:の一部です Pythonの「データモデル」. 。つまり、その動作は、 __eq__
方法。例えば:
class MyClass(object):
def __init__(self, val):
self._value = val
def __eq__(self, other):
print('__eq__ method called')
try:
return self._value == other._value
except AttributeError:
raise TypeError('Cannot compare {0} to objects of type {1}'
.format(type(self), type(other)))
これは、メソッドが実際に呼び出されることを示すための単なる人工的な例です。
>>> MyClass(10) == MyClass(10)
__eq__ method called
True
デフォルトでは(他の実装がない場合)、 __eq__
クラスまたはスーパークラスで見つけることができます) __eq__
用途 is
:
class AClass(object):
def __init__(self, value):
self._value = value
>>> a = AClass(10)
>>> b = AClass(10)
>>> a == b
False
>>> a == a
したがって、実際に実装することが重要です __eq__
カスタム クラスの参照比較以上のものが必要な場合は、
逆にカスタマイズはできない is
小切手。必ず比較してしまう ただ 同じリファレンスをお持ちの場合。
これらの比較では常にブール値が返されるのでしょうか?
なぜなら __eq__
再実装またはオーバーライドできます。戻りに限定されません。 True
または False
. 。それ できた 何でも返します (ただし、ほとんどの場合はブール値を返す必要があります)。
たとえば、NumPy 配列の場合、 ==
配列を返します:
>>> import numpy as np
>>> np.arange(10) == 2
array([False, False, True, False, False, False, False, False, False, False], dtype=bool)
しかし is
小切手は必ず戻ってきます True
または False
!
1 アーロン・ホールはコメントで次のように述べています。
一般的には何もすべきではありません is True
または is False
チェックは、通常、暗黙的に変換するコンテキストでこれらの「チェック」を使用するためです。 状態 ブール値に (たとえば、 if
声明)。それで、 is True
比較 そして 暗黙的なブール キャストは、ブール キャストを実行するだけではなく、より多くの作業を実行します。また、ブール値に制限します (これは Python とみなされません)。
PEP8 が言及しているように:
ブール値を比較しないでください
True
またはFalse
使用して==
.Yes: if greeting: No: if greeting == True: Worse: if greeting is True:
彼らです 全然違う. is
オブジェクトのアイデンティティをチェックしますが、 ==
等しいかどうかをチェックします (2 つのオペランドの型に依存する概念)。
それは単なる幸運な偶然です。」is
" は小さな整数では正しく動作するようです (例:5 == 4+1)。それは、 CPython は、整数をシングルトンにすることで、範囲 (-5 ~ 256) の整数のストレージを最適化します。. 。この動作は完全に実装に依存しており、あらゆる種類のマイナーな変換操作の下で維持されることは保証されません。
たとえば、Python 3.5 も短い文字列をシングルトンにしますが、それらをスライスするとこの動作が中断されます。
>>> "foo" + "bar" == "foobar"
True
>>> "foo" + "bar" is "foobar"
True
>>> "foo"[:] + "bar" == "foobar"
True
>>> "foo"[:] + "bar" is "foobar"
False
https://docs.python.org/library/stdtypes.html#comparisons
is
身元を調べるテスト==
平等性をテストする
それぞれの (小さい) 整数値は単一の値にマップされるため、すべての 3 は同一であり、等しいです。これは実装の詳細であり、言語仕様の一部ではありませんが、
あなたの答えは正しいです。の is
演算子は 2 つのオブジェクトの同一性を比較します。の ==
演算子は 2 つのオブジェクトの値を比較します。
オブジェクトのアイデンティティは、一度作成されると決して変更されません。これはメモリ内のオブジェクトのアドレスと考えることができます。
オブジェクト値の比較動作を制御するには、 __cmp__
方法または 豊富な比較 のような方法 __eq__
.
の ==
演算子は両方のオペランドの値を比較し、値が等しいかどうかをチェックします。一方 is
演算子は、両方のオペランドが同じオブジェクトを参照しているかどうかをチェックします。
a = [1,2,3,4]
b = a
print(a == b) # true
print(a is b) # true
しかし、そうすれば
b = a[:] # b now references a copy of a
print(a == b) # true
print(a is b) # false
print(a is not b) # true
基本的に、 is
の短縮形と考えることができます id(a) == id(b)
. 。ただし、これに加えて、実行時環境には問題をさらに複雑にする癖があります。短い文字列と小さな整数が返されます True
と比較した場合 is
, Python マシンが同一のオブジェクトに対して使用するメモリの量を減らそうとするためです。
a = 'python'
b = 'python'
print(a == b) # true
print(a is b) # true
Stack Overflow の質問を見てください。 Python の「is」演算子が整数に対して予期しない動作をする.
それは主に要約すると、次のようなものです。is
" は、それらが互いに等しいだけでなく、同じオブジェクトであるかどうかを確認します (256 未満の数値は特殊なケースです)。
John Feminella 氏が述べたように、目的は値を比較することなので、ほとんどの場合 == と != を使用します。残りの時間に何をするかを分類したいと思います。
NoneType のインスタンスは 1 つだけです。どれもシングルトンではありません。その結果 foo == None
そして foo is None
同じ意味です。しかし is
テストはより高速であり、Python の規約では次のように使用されます。 foo is None
.
イントロスペクションを行ったり、ガベージ コレクションをいじったり、カスタム構築した文字列インターニング ガジェットが機能しているかどうかをチェックしたりしている場合は、おそらく次のようなユースケースがあるでしょう。 foo
は bar
.
True と False も (現在は) シングルトンですが、そのユースケースはありません。 foo == True
ユースケースはありません foo is True
.
彼らのほとんどはすでに要点に答えています。追加のメモとして(文書化されたソースからではなく、私の理解と実験に基づいています)、次のステートメント
== 変数によって参照されるオブジェクトが等しい場合
上記の答えは次のように読む必要があります
== 変数によって参照されるオブジェクトが等しく、オブジェクトが同じ型/クラスに属している場合
. 。私は以下のテストに基づいてこの結論に達しました。
list1 = [1,2,3,4]
tuple1 = (1,2,3,4)
print(list1)
print(tuple1)
print(id(list1))
print(id(tuple1))
print(list1 == tuple1)
print(list1 is tuple1)
ここではリストとタプルの内容は同じですが、型/クラスが異なります。
一言で言えば、 is
2 つの参照が同じオブジェクトを指しているかどうかをチェックします。==
2 つのオブジェクトが同じ値を持つかどうかを確認します。
a=[1,2,3]
b=a #a and b point to the same object
c=list(a) #c points to different object
if a==b:
print('#') #output:#
if a is b:
print('##') #output:##
if a==c:
print('###') #output:##
if a is c:
print('####') #no output as c and a point to different object
実際、これをコメントとして追加したかったのですが、簡単に美化できなかったため、回答として追加しました。これを回答とはみなさないでください。
これが私が理解するためにやったことです --
以下を 1 つずつ実行し、各ステップの出力を理解する
a = [1,2]
b = [1,2,3]
b.pop()
id(a)
id(b)
a is b
a == b
この投稿の他の人が質問に詳しく答えているので、私は 強調する 主に以下の比較 is
そして ==
文字列用 これらは異なる結果をもたらす可能性があるため、プログラマーには慎重に使用することをお勧めします。
文字列比較の場合は、必ず使用してください ==
の代わりに is
:
str = 'hello'
if (str is 'hello'):
print ('str is hello')
if (str == 'hello'):
print ('str == hello')
外:
str is hello
str == hello
しかし 以下の例では ==
そして is
異なる結果が得られます:
str = 'hello sam'
if (str is 'hello sam'):
print ('str is hello sam')
if (str == 'hello sam'):
print ('str == hello sam')
外:
str == hello sam
結論:
使用 is
文字列間を注意深く比較する
Pythonのisとequals(==)の違い
ISオペレーターは、平等演算子と同じように見えるかもしれませんが、それらは同じではありません。
ISは、両方の変数が同じオブジェクトを指しているかどうかをチェックしますが、==サインは2つの変数の値が同じかどうかをチェックします。
したがって、ISオペレーターがtrueを返す場合、平等は間違いなく真実ですが、反対が真実である場合とそうでない場合があります。
類似点と相違点を示す例を次に示します。
>>> a = b = [1,2,3]
>>> c = [1,2,3]
>>> a == b
True
>>> a == c
True
>>> a is b
True
>>> a is c
False
>>> a = [1,2,3]
>>> b = [1,2]
>>> a == b
False
>>> a is b
False
>>> del a[2]
>>> a == b
True
>>> a is b
False
Tip: Avoid using is operator for immutable types such as strings and numbers, the result is unpredictable.
「==」は値を比較します
「is」は基礎となるオブジェクトを比較します
# this pgm is to show you the diff b/n == and is
# a==b and a is b
# == compares values
# is compares references i.e compares wether two variables refer to same object(memory)
a=10
b=10
print(a==b) # returns True as a,b have same value 10
print(a is b)
# returns True,
# we usually falsey assume that a =10 a new object . b=10 a new obj created
# but actually when b=10 ,nothing but b is pointed to 10 until value of a or b is changed from 10
a=[1]
b=[1]
print(a==b)
#returns True as a,b have a list element 1
print(a is b)
#returns False because here two different objs are created when initiated with lists
o1はo2です => o1 と o2 が両方ともメモリ内の同じ物理位置を指しているかどうか (つまり、同じオブジェクトであるかどうか) を比較します。
o1 == o2 => ここで、Python は o1 の __cmp __(o2) メソッドを呼び出します。理想的には、値を比較して True または False を返す必要があります。(つまり値を比較します)
JAVA の人向け:
Javaで、2つの文字列変数が使用して同じ物理メモリの位置を参照するかどうかを判断する str1 == str2. 。(オブジェクトアイデンティティと呼ばれ、に書かれています Python の str1 が str2 になる).
Java で文字列値を比較するには、 usestr1.equals(str2);で python、str1 == str2を使用します.
例:
class A():
...: def __init__(self,a):
...: self.a = a
...: def __repr__(self):
...: return str(self.a)
...: def __cmp__(self, value):
...: print self.a
...: print value.a
...: return cmp(self.a, value.a)
Python シェルの出力:
o = a(2)o1 = o
o == o1 2 2 true
oはo1 trueです
o1 = A(2)
oはo1 falseです
JavaScript と比較すると (ただし、ある言語と別の言語を比較することはお勧めできません):
- 使用
is
厳密な比較のため。同等の Javascript (===
) - 使用
==
等価比較用。
オブジェクトポインタの比較と値の比較の実装に依存するこれらの答えはすべて正しいと思われますが、使用するより深い構文上の理由があります。 is
変数値が以下であるかどうかを判断するには None
(ブール論理では、次のように表されることがよくあります) NULL
).
リレーショナル データベースやその他の論理システムでは、 NULL
実際の値が「不明」であることを意味します。したがって、論理式は xx == NULL
常に次のように評価する必要があります NULL
それ自体、それを知ることは決して不可能であるため、 xx
, は、どのような値であっても、未知の値と同じです。ブール論理のルールをより厳密に遵守するプログラミング言語では、 xx == NULL
(またはPython的に xx == None
) は正しく評価されます NULL
, であり、変数値が NULL
. 。Python は、オブジェクト参照の単一性の性質により、この点では外れ値です。 None
. 。ただし、明確さと論理的正確さのために、Python を使用します。 is
比較演算子を使用する方がはるかに健全な方法であるように私には思えます。
はい、両方に違いがあります。
- '==' :オブジェクトを値で比較します。
'で' :オブジェクトを参照により比較します。
a = [1,2,3] b = a # both pointing to same object (memory location) a == b: True a in b: True #because a and b are pointing to same object
次に、このケースを考えてみましょう。
a = [1,2,3]
b = list(a) # creating copy of object a
a == b:
True # as values are same
a in b:
False # because they are pointing to different object.