この質問 のコメントで、使用することを推奨するステートメントを見ました
result is not None
対
result != None
私は違いが何であり、なぜ一方が他方よりも推奨されるのだろうと思っていましたか?
==
は等価テストです。右側と左側が等しいオブジェクトであるかどうかをチェックします(それらの__eq__
または__cmp__
メソッドによる)。
is
は同一性テストです。右側と左側がまったく同じオブジェクトかどうかをチェックします。メソッド呼び出しは行われません。オブジェクトはis
操作に影響を与えることはできません。
is
のふりをしたいオブジェクトを気にしない場合、またはNone
と比較したときにオブジェクトが壊れないように保護する場合は、None
などのシングルトンにNone
(およびis not
)を使用します。
まず、いくつかの用語を見てみましょう。質問に回答するだけの場合は、「質問への回答」までスクロールします。
オブジェクトID:オブジェクトを作成するときに、変数に割り当てることができます。その後、別の変数に割り当てることもできます。そしてもう一つ。
>>> button = Button()
>>> cancel = button
>>> close = button
>>> dismiss = button
>>> print(cancel is close)
True
この場合、cancel
、close
、およびdismiss
はすべて、メモリ内の同じオブジェクトを参照します。 Button
オブジェクトを1つだけ作成し、3つの変数はすべてこの1つのオブジェクトを参照しています。 cancel
、close
、およびdismiss
はすべてidenticalオブジェクトを参照すると言います。つまり、1つのオブジェクトを参照します。
オブジェクトの等価性:2つのオブジェクトを比較する場合、通常、メモリ内の同じオブジェクトexactを参照していることは気にしません。オブジェクトの等価性により、2つのオブジェクトの比較方法について独自のルールを定義できます。 if a == b:
と書くと、本質的にif a.__eq__(b):
と言っていることになります。これにより、a
で__eq__
メソッドを定義できるため、独自の比較ロジックを使用できます。
理由: 2つのオブジェクトのデータはまったく同じですが、同一ではありません。 (メモリ内の同じオブジェクトではありません。)例:文字列
>>> greeting = "It's a beautiful day in the neighbourhood."
>>> a = unicode(greeting)
>>> b = unicode(greeting)
>>> a is b
False
>>> a == b
True
注:Pythonはメモリに新しい文字列を作成せずに通常の文字列を再利用できるほどスマートなので、ここではUnicode文字列を使用します。
ここには、a
とb
という2つのUnicode文字列があります。内容はまったく同じですが、メモリ内の同じオブジェクトではありません。ただし、それらを比較するときは、同等に比較する必要があります。ここで起こっているのは、unicodeオブジェクトが__eq__
メソッドを実装していることです。
class unicode(object):
# ...
def __eq__(self, other):
if len(self) != len(other):
return False
for i, j in Zip(self, other):
if i != j:
return False
return True
注:unicode
の__eq__
は、これよりも確実に効率的に実装されます。
理由: 2つのオブジェクトのデータは異なりますが、一部のキーデータが同じ場合は同じオブジェクトと見なされます。 例:ほとんどのタイプのモデルデータ
>>> import datetime
>>> a = Monitor()
>>> a.make = "Dell"
>>> a.model = "E770s"
>>> a.owner = "Bob Jones"
>>> a.warranty_expiration = datetime.date(2030, 12, 31)
>>> b = Monitor()
>>> b.make = "Dell"
>>> b.model = "E770s"
>>> b.owner = "Sam Johnson"
>>> b.warranty_expiration = datetime.date(2005, 8, 22)
>>> a is b
False
>>> a == b
True
ここには、a
とb
という2つのDellモニターがあります。彼らは同じメーカーとモデルを持っています。ただし、それらは同じデータもメモリ内の同じオブジェクトでもありません。ただし、それらを比較するときは、同等に比較する必要があります。ここで何が起きているかは、Monitorオブジェクトが__eq__
メソッドを実装していることです。
class Monitor(object):
# ...
def __eq__(self, other):
return self.make == other.make and self.model == other.model
None
と比較するときは、常にis not
を使用してください。 Pythonにはシングルトンはありません-メモリにはインスタンスが1つしかありません。
identityを比較することにより、これを非常に迅速に実行できます。 Pythonは、参照しているオブジェクトがグローバルNoneオブジェクトと同じメモリアドレスを持っているかどうかを確認します-2つの数値の非常に高速な比較。
equalityを比較することにより、Pythonはオブジェクトに__eq__
メソッドがあるかどうかを調べる必要があります。そうでない場合は、各スーパークラスを調べて__eq__
メソッドを探します。見つかった場合、Pythonはそれを呼び出します。これは、__eq__
メソッドが遅く、他のオブジェクトがNone
であることに気付いたときにすぐに返らない場合、特に悪いです。
__eq__
を実装しませんでしたか? Pythonは、おそらくobject
で__eq__
メソッドを見つけ、代わりにそれを使用します-とにかくオブジェクトのIDをチェックするだけです。
Pythonで他のほとんどのものを比較するときは、!=
を使用します。
以下を考慮してください。
class Bad(object):
def __eq__(self, other):
return True
c = Bad()
c is None # False, equivalent to id(c) == id(None)
c == None # True, equivalent to c.__eq__(None)
None
はシングルトンなので、ID比較は常に機能しますが、オブジェクトは.__eq__()
を介して等値比較を偽造できます。
>>>()is() True >>> 1 is 1 True >>>(1、)== (1、) True >>>(1、)は(1、) False >>> a =(1、) >>> b = a >>> a is b True
一部のオブジェクトはシングルトンであるため、is
とそれらは==
と同等です。ほとんどはそうではありません。