この質問へのコメントで、私は使用を推奨する声明を見ました
result is not None
対
result != None
私は違いが何であるのか、そしてなぜ一方が他方よりも推奨されるのか疑問に思っていましたか?
この質問へのコメントで、私は使用を推奨する声明を見ました
result is not None
対
result != None
私は違いが何であるのか、そしてなぜ一方が他方よりも推奨されるのか疑問に思っていましたか?
回答:
==
ある平等テストが。右側と左側が等しいオブジェクトであるかどうかを確認します(__eq__
またはそれらの__cmp__
メソッドに従って)。
is
あるアイデンティティテストが。右側と左側がまったく同じオブジェクトかどうかをチェックします。メソッド呼び出しは行われませんis
。オブジェクトは操作に影響を与えることができません。
のようなシングルトンに対してis
(およびis not
)を使用します。たとえばNone
、ふりをする可能性のあるオブジェクトが気にならない場合None
や、と比較したときにオブジェクトが壊れないように保護する場合ですNone
。
None
メソッドはほとんどなく、属性はほとんどありません。__eq__
テストでメソッドまたは属性が想定されていた場合、それが壊れる可能性があります。 def __eq__( self, other ): return self.size == other.size
。たとえば、other
たまたまあると壊れますNone
。
is
はJavaのようなもの==
です。Python ==
はJavaに似ています.equals()
。もちろん、これはJavaを知っている場合にのみ役立ちます。
is
ようなものです===
(非常に等しい)、逆is not
に似ている!==
(正確に一致しません)。
is not
一人のオペレータは、またはそれだけの結果を否定されたis
ように、内部not foo is bar
?
最初に、いくつかの用語について説明します。質問への回答を希望する場合は、「質問への回答」までスクロールしてください。
オブジェクトID:オブジェクトを作成するときに、オブジェクトを変数に割り当てることができます。その後、別の変数に割り当てることもできます。そしてもう一つ。
>>> button = Button()
>>> cancel = button
>>> close = button
>>> dismiss = button
>>> print(cancel is close)
True
この場合、cancel
、close
、およびdismiss
すべてのメモリ内の同じオブジェクトを参照。作成したButton
オブジェクトは1つだけで、3つの変数すべてがこの1つのオブジェクトを参照しています。我々はそれを言うcancel
、close
と、dismiss
すべての参照と同じオブジェクト。つまり、1つのオブジェクトを参照します。
オブジェクトの等価性:2つのオブジェクトを比較する場合、通常、メモリ内のまったく同じオブジェクトを参照していることは気にしません。オブジェクトの等価性を使用すると、2つのオブジェクトの比較方法に関する独自のルールを定義できます。あなたが書くときif a == b:
、あなたは本質的に言っていif a.__eq__(b):
ます。これにより、独自の比較ロジックを使用できるように__eq__
メソッドを定義できますa
。
理論的根拠: 2つのオブジェクトはまったく同じデータを持っていますが、同一ではありません。(これらはメモリ内の同じオブジェクトではありません。) 例:文字列
>>> greeting = "It's a beautiful day in the neighbourhood."
>>> a = unicode(greeting)
>>> b = unicode(greeting)
>>> a is b
False
>>> a == b
True
注:ここではユニコード文字列を使用しています。Pythonは、メモリに新しい文字列を作成せずに通常の文字列を再利用できるほどスマートだからです。
ここでは、2つのUnicode文字列とがa
ありb
ます。内容はまったく同じですが、メモリ内の同じオブジェクトではありません。ただし、それらを比較する場合は、同等に比較する必要があります。ここで起こっていることは、ユニコードオブジェクトが__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
注:__eq__
on unicode
は間違いなくこれよりも効率的に実装されています。
理論的根拠: 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
ここには、2台のDellモニターとがa
ありb
ます。彼らは同じメーカーとモデルを持っています。ただし、それらは同じデータもメモリ内の同じオブジェクトもありません。ただし、それらを比較する場合は、同等に比較する必要があります。ここで起こっているのは、Monitorオブジェクトが__eq__
メソッドを実装したことです。
class Monitor(object):
# ...
def __eq__(self, other):
return self.make == other.make and self.model == other.model
と比較する場合はNone
、常にを使用してくださいis not
。Pythonのシングルトンはありません。メモリに存在するインスタンスは1つだけです。
アイデンティティを比較することにより、これは非常に迅速に実行できます。Pythonは、参照しているオブジェクトがグローバルのNoneオブジェクトと同じメモリアドレスを持っているかどうかをチェックします-2つの数値を非常に高速に比較します。
等価性を比較することにより、Pythonはオブジェクトに__eq__
メソッドがあるかどうかを調べる必要があります。そうでない場合は、各スーパークラスを調べて__eq__
メソッドを探します。見つかった場合、Pythonはそれを呼び出します。これは、__eq__
メソッドが遅く、他のオブジェクトがであることに気付いてもすぐには返らない場合に特に悪いですNone
。
実装しませんでした__eq__
か?次に、Pythonはおそらく__eq__
メソッドを見つけobject
て代わりに使用します-これはとにかくオブジェクトのアイデンティティをチェックするだけです。
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
はシングルトンであるため、恒等比較は常に機能しますが、オブジェクトはを介して等価比較を偽造できます.__eq__()
。
None
、None
他の型に対する等価性を実装することの副作用として、に関する不正な動作が発生する可能性があります。それは正確さの意味合いであるので、それはそれほどセキュリティの意味合いではありません。
>>>()は() 本当 >>> 1は1 本当 >>>(1、)==(1、) 本当 >>>(1、)は(1、)です 誤り >>> a =(1、) >>> b = a >>> aはb 本当
一部のオブジェクトはシングルトンであるためis
、それらを使用するとと同等になり==
ます。ほとんどはそうではありません。
()
そして1
本質的にシングルトンではありません。
-NSMALLNEGINTS <= n <= NSMALLPOSINTS
)と空のタプルはシングルトンです。実際、文書化も保証もされていませんが、変更される可能性はほとんどありません。