私の 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.
==
はvalueをテストし、is
はそれらが同じオブジェクトであるかどうかをテストしますか?
is
は、2つの変数が同じオブジェクトを指す場合はTrue
を返し、変数によって参照されるオブジェクトが等しい場合は==
を返します。
>>> 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
あなたの場合、2番目のテストはPythonが小さな整数オブジェクトをキャッシュしているためにのみ機能します。これは実装の詳細です。これより大きい整数の場合、これは機能しません。
>>> 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つの参照が同じオブジェクトを参照しているかどうかを知りたいときに使用してください。一般的に、何かを単純な型と比較するときは、通常、 value equality をチェックしているので、==
を使用する必要があります。たとえば、あなたの例の意図はおそらく、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
を使用しないもう1つの明白な理由です。値の等価性のために誤って使用している場合、動作は実装に任されています。
==
は値が等しいかどうかを決定し、is
はそれらがまったく同じオブジェクトで等しいかどうかを決定します。
Pythonの
==
とis
に違いはありますか?
はい、彼らは非常に重要な違いがあります。
==
:等しいかどうかをチェックする - 意味は同等のオブジェクト(必ずしも同じオブジェクトではない)が等しいとテストするということです。 ドキュメンテーションが言うように :
演算子<、>、==、> =、<=、および!=は、2つのオブジェクトの値を比較します。
is
:アイデンティティのチェック - 意味はオブジェクト(メモリに保持されている)isオブジェクトです。繰り返しますが、 のドキュメントには :と書かれています。
演算子
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
に設定されている変数または引数が他の値に設定されているかどうかをテストするとき。他の値には、ブール値のコンテキストではfalseになる可能性がある型(コンテナなど)があります。
is
がtrueの場合、等価性は通常 _と推測できます。論理的には、オブジェクトがそれ自体であれば、それはそれ自体と同等であるとテストする必要があります。
ほとんどの場合、このロジックは正しいですが、__eq__
特殊メソッドの実装に依存しています。 docs と言うように、
等価比較(
==
および!=
)のデフォルトの動作は、オブジェクトの識別情報に基づいています。したがって、同一の同一性を持つインスタンスの等価性比較は等価になり、異なる同一性のインスタンスの等価性比較は不等式になります。このデフォルトの振る舞いの動機は、すべてのオブジェクトが再帰的であるべきであるという欲求です(すなわち、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
を使用しようとしています。あなたは整数のインスタンスが他の参照によって得られるものと同じインスタンスであると仮定するべきではありません。この話はその理由を説明しています。
コメント者は、等しいかどうかをチェックするのではなく、小さい整数(-5から256まで)がPythonのシングルトンであるという事実に依存するコードを持っていました。
うわー、これはいくつかの潜行性のバグにつながる可能性があります。 aがbであるかどうかをチェックするコードをいくつか持っていました。aとbは通常小さい数字なので、期待通りに動作しました。このバグは、運用開始から6か月経った今日でのみ発生しました。aとbは、最終的にキャッシュされないほどの大きさだったためです。 - gwg
それは開発で働いた。それはいくつかの単体テストに合格した可能性があります。
そしてコードは256より大きい整数をチェックするまでプロダクションではうまくいきましたが、その時点ではプロダクションで失敗しました。
これはコードレビューやスタイルチェッカーでつかまえられたかもしれない生産上の失敗です。
強調しておきましょう:整数を比較するためにis
を使用しないでください。
彼らです 全然違う。 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
is
と==
の違いは何ですか?==
とis
は異なる比較です。他の人がすでに言ったように:
==
はオブジェクトの値を比較します。is
は、オブジェクトの参照を比較します。Pythonでは、名前はオブジェクトを参照します。たとえば、この場合value1
とvalue2
は、値1000
を格納するint
インスタンスを参照します。
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
を使用してください。
値を Python 定数 と比較したい。 Pythonの定数は次のとおりです。
None
True
1False
1NotImplemented
Ellipsis
__debug__
int is int
またはint is float
)np.ma.masked
NumPyモジュールから) その他の場合には、等価性をチェックするために==
を使うべきです。
==
には他の答えではまだ触れられていない側面があります: Pythonsの "Data model" の一部です。つまり、 __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
チェックをカスタマイズすることはできません。同じ参照がある場合は、常にjustが比較されます。
__eq__
は再実装またはオーバーライドできるので、True
またはFalse
を返すことに限定されません。それはcouldを返します(しかしほとんどの場合それはブール値を返すべきです!).
例えば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
のチェックは、暗黙のうちにconditionをブール値に変換する文脈(例えばif
ステートメントなど)で通常使用されるため、通常は使用しないでください。そのため、is True
比較 と を実行すると、暗黙のブールキャストは単にブールキャストを実行するよりも多くの作業を実行することになります。
PEP8の言及のように:
==
を使ってブール値をTrue
またはFalse
と比較しないでください。Yes: if greeting: No: if greeting == True: Worse: if greeting is True:
https://docs.python.org/library/stdtypes.html#comparisons
is
は同一性をテストする==
は同一性をテストする
それぞれの(小さい)整数値は単一の値にマップされるので、3つごとに同一で等しくなります。これは実装の詳細であり、言語仕様の一部ではありません
あなたの答えは正しいです。 is
演算子は、2つのオブジェクトの同一性を比較します。 ==
演算子は、2つのオブジェクトの値を比較します。
オブジェクトのIDは、いったん作成されると変更されることはありません。あなたはそれをメモリ内のオブジェクトのアドレスと考えることができます。
__cmp__
メソッドまたは__eq__
のような richの比較 メソッドを定義することで、オブジェクト値の比較動作を制御できます。
Stack Overflow questionを見てください。Pythonの「is」演算子は整数で予期せず動作します。
それが大まかに言うと、 "is
"はそれらが同じオブジェクトであるかどうかを調べるためにチェックします。
==
演算子は、両方のオペランドの値を比較し、値が等しいかどうかを確認します。 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
彼らのほとんどはすでにその点に答えています。補足的なメモとして(私の理解と実験に基づいていますが、文書化されたソースからのものではありません)
==変数によって参照されるオブジェクトが等しい場合
上記の答えからのように読まれるべきです
==変数によって参照されるオブジェクトが等しく、オブジェクトが同じタイプ/クラスに属する場合
。私は以下のテストに基づいてこの結論に達しました。
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)
ここでリストとTupleの内容は同じですが、型/クラスは異なります。
John Feminellaが言ったように、あなたの目的は値を比較することなので、ほとんどの場合==と!=を使うでしょう。残りの時間にあなたがすることを分類したいのですが。
NoneTypeにはただ1つのインスタンスしかありません。すなわち、Noneはシングルトンです。したがって、foo == None
とfoo is None
は同じ意味です。しかしis
テストはより速く、Pythonicの慣習はfoo is None
を使うことです。
イントロスペクションをしたり、ガベージコレクションを行ったり、カスタム作成された文字列インターナリングガジェットが機能しているかどうかをチェックしている場合、おそらくfoo
のユースケースはbar
です。
TrueとFalseも(今のところ)シングルトンですが、foo == True
のユースケースとfoo is True
のユースケースはありません。
一言で言えば、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
実際に私はこれをコメントとして追加したいのですが、それを簡単に美化することはできませんでしたので答えとして追加しました。これを答えとしては考えないでください。
これは私が理解するためにしたことです -
一つずつフォローを実行し、各ステップの出力を理解する
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
以下の例のbut==
と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
を慎重に使って文字列を比較する
Isとequals(==)のPythonの違い
Is演算子は、等価演算子と同じように見えるかもしれませんが、同じではありません。
Isは両方の変数が同じオブジェクトを指しているかどうかをチェックし、==記号は2つの変数の値が同じかどうかをチェックします。
したがって、is演算子がTrueを返す場合、等価性は確実にTrueですが、その逆は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.
JavaScriptと比較すると(ただし、ある言語と別の言語を比較することはお勧めできません)。
is
を使用してください。 Javascriptと同等のもの(===
)==
を使用してください。