web-dev-qa-db-ja.com

"=="と "is"の間は違いますありますか?

私の 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はそれらが同じオブジェクトであるかどうかをテストしますか?

604
Bernard

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

この質問 もご覧ください。

812
Torsten Marek

==またはisをいつ使用するかを告げる簡単な経験則があります。

  • == 値の等価性 のためのものです。 2つのオブジェクトが同じ値を持っているかどうかを知りたいときに使用してください。
  • is 参照等価 のためのものです。 2つの参照が同じオブジェクトを参照しているかどうかを知りたいときに使用してください。

一般的に、何かを単純な型と比較するときは、通常、 value equality をチェックしているので、==を使用する必要があります。たとえば、あなたの例の意図はおそらく、xが文字通り2と同じオブジェクトを参照しているかどうかではなく、xが2(==)に等しい値を持つかどうかをチェックすることです。


注意しなければならないことがあります:CPythonのリファレンス実装が機能する方法のため、誤ってisを使用して整数のリファレンス等価性を比較すると、予期しない矛盾する結果が得られます。

>>> a = 500
>>> b = 500
>>> a == b
True
>>> a is b
False

abは同じ値を持ちますが、別々のエンティティです。しかし、これはどうですか?

>>> 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つの明白な理由です。値の等価性のために誤って使用している場合、動作は実装に任されています。

273
John Feminella

==は値が等しいかどうかを決定し、isはそれらがまったく同じオブジェクトで等しいかどうかを決定します。

33
stephenbayer

Pythonの==isに違いはありますか?

はい、彼らは非常に重要な違いがあります。

==:等しいかどうかをチェックする - 意味は同等のオブジェクト(必ずしも同じオブジェクトではない)が等しいとテストするということです。 ドキュメンテーションが言うように

演算子<、>、==、> =、<=、および!=は、2つのオブジェクトの値を比較します。

is:アイデンティティのチェック - 意味はオブジェクト(メモリに保持されている)isオブジェクトです。繰り返しますが、 のドキュメントには :と書かれています。

演算子isis notは、オブジェクトの同一性をテストします。x is yは、xyが同じオブジェクトである場合に限り、真になります。オブジェクトの同一性はid()関数を使って決定されます。 x is not yは、逆の真理値を返します。

したがって、同一性の確認は、オブジェクトのIDが等しいことを確認することと同じです。あれは、

a is b

と同じです。

id(a) == id(b)

ここでidは「同時に存在するオブジェクト間で一意であることが保証されている」整数を返す組み込み関数で(help(id)を参照)、abは任意のオブジェクトです。

その他の使用方法

あなたはそれらの意味論のためにこれらの比較を使うべきです。同一性をチェックするには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 yx == 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を使用しないでください。

22
Aaron Hall

彼らです 全然違う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
17
Dan Lenski

is==の違いは何ですか?

==isは異なる比較です。他の人がすでに言ったように:

  • ==はオブジェクトの値を比較します。
  • isは、オブジェクトの参照を比較します。

Pythonでは、名前はオブジェクトを参照します。たとえば、この場合value1value2は、値1000を格納するintインスタンスを参照します。

value1 = 1000
value2 = value1

enter image description here

value2は同じオブジェクトis==を参照するため、Trueは次のようになります。

>>> value1 == value2
True
>>> value1 is value2
True

次の例では、value1value2という名前は、両方が同じ整数を格納している場合でも、異なるintインスタンスを参照します。

>>> value1 = 1000
>>> value2 = 1000

enter image description here

同じ値(整数)が格納されているので==Trueになります、それがしばしば「値比較」と呼ばれる理由です。ただし、isFalseを返します。これらはオブジェクトが異なるためです。

>>> value1 == value2
True
>>> value1 is value2
False

いつ使うの?

一般的にisははるかに速い比較です。これが、CPythonが小さな整数や文字列などのような特定のオブジェクトをキャッシュする(あるいは再利用がおそらくより良い用語になる)理由です。しかしこれは実装の詳細として扱うことができます。ほとんどの場合、警告なしにいつでも変更できます。

次の場合にのみisを使用してください。

  • 2つのオブジェクトが本当に同じオブジェクトであるかどうかをチェックしたい(単に同じ「値」ではない)。一例として、youがシングルトンオブジェクトを定数として使用する場合があります。
  • 値を Python 定数 と比較したい。 Pythonの定数は次のとおりです。

    • None
    • True1
    • False1
    • NotImplemented
    • 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 Trueis Falseのチェックは、暗黙のうちにconditionをブール値に変換する文脈(例えばifステートメントなど)で通常使用されるため、通常は使用しないでください。そのため、is True比較を実行すると、暗黙のブールキャストは単にブールキャストを実行するよりも多くの作業を実行することになります。

PEP8の言及のように:

==を使ってブール値をTrueまたはFalseと比較しないでください。

Yes:   if greeting:
No:    if greeting == True:
Worse: if greeting is True:
16
MSeifert

https://docs.python.org/library/stdtypes.html#comparisons

isは同一性をテストする==は同一性をテストする

それぞれの(小さい)整数値は単一の値にマップされるので、3つごとに同一で等しくなります。これは実装の詳細であり、言語仕様の一部ではありません

10
mmaibaum

あなたの答えは正しいです。 is演算子は、2つのオブジェクトの同一性を比較します。 ==演算子は、2つのオブジェクトの値を比較します。

オブジェクトのIDは、いったん作成されると変更されることはありません。あなたはそれをメモリ内のオブジェクトのアドレスと考えることができます。

__cmp__メソッドまたは__eq__のような richの比較 メソッドを定義することで、オブジェクト値の比較動作を制御できます。

6
Dave Webb

Stack Overflow questionを見てください。Pythonの「is」演算子は整数で予期せず動作します。

それが大まかに言うと、 "is"はそれらが同じオブジェクトであるかどうかを調べるためにチェックします。

4
cobbal

==演算子は、両方のオペランドの値を比較し、値が等しいかどうかを確認します。 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

基本的に、isid(a) == id(b)の省略形と考えることができます。しかし、これ以外にも、ランタイム環境にはさらに複雑なことがあります。短い文字列と小さな整数は、Trueと比較してisを返します。これは、Pythonマシンが同一のオブジェクトに使用するメモリを少なくしようとしたためです。

a = 'python'
b = 'python'

print(a == b) # true
print(a is b) # true
3
iNet

彼らのほとんどはすでにその点に答えています。補足的なメモとして(私の理解と実験に基づいていますが、文書化されたソースからのものではありません)

==変数によって参照されるオブジェクトが等しい場合

上記の答えからのように読まれるべきです

==変数によって参照されるオブジェクトが等しく、オブジェクトが同じタイプ/クラスに属する場合

。私は以下のテストに基づいてこの結論に達しました。

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の内容は同じですが、型/クラスは異なります。

2
Sandeep

John Feminellaが言ったように、あなたの目的は値を比較することなので、ほとんどの場合==と!=を使うでしょう。残りの時間にあなたがすることを分類したいのですが。

NoneTypeにはただ1つのインスタンスしかありません。すなわち、Noneはシングルトンです。したがって、foo == Nonefoo is Noneは同じ意味です。しかしisテストはより速く、Pythonicの慣習はfoo is Noneを使うことです。

イントロスペクションをしたり、ガベージコレクションを行ったり、カスタム作成された文字列インターナリングガジェットが機能しているかどうかをチェックしている場合、おそらくfooのユースケースはbarです。

TrueとFalseも(今のところ)シングルトンですが、foo == Trueのユースケースとfoo is Trueのユースケースはありません。

2
John Machin

一言で言えば、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 
2
suvojit_007

実際に私はこれをコメントとして追加したいのですが、それを簡単に美化することはできませんでしたので答えとして追加しました。これを答えとしては考えないでください。

これは私が理解するためにしたことです -

一つずつフォローを実行し、各ステップの出力を理解する

a = [1,2]
b = [1,2,3]
b.pop()
id(a)
id(b)
a is b
a == b
1
Pranav

この記事の他の人たちが詳細に質問に答えるので、私は強調 _ 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を慎重に使って文字列を比較する

1
imanzabet

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.
0
Projesh Bhoumik

JavaScriptと比較すると(ただし、ある言語と別の言語を比較することはお勧めできません)。

  • 厳密な比較にはisを使用してください。 Javascriptと同等のもの(===
  • 等価比較には==を使用してください。
0