「foo is None」と「foo == None」の違いはありますか?


217

違いはありますか:

if foo is None: pass

そして

if foo == None: pass

ほとんどのPythonコード(および私自身が作成したコード)で見た慣習は前者ですが、最近、後者を使用するコードに出くわしました。NoneはNoneTypeのインスタンス(および唯一のインスタンス、IIRC)であるため、重要ではありませんか?それが起こり得る状況はありますか?

回答:


253

is 常に戻る True同じオブジェクトインスタンスを比較する場合はます

一方==、最終的に決定されるのは__eq__()方法

すなわち


>>> class Foo(object):
       def __eq__(self, other):
           return True

>>> f = Foo()
>>> f == None
True
>>> f is None
False

51
Noneはシングルトンであるため、「None is None」は常にTrueであることを追加できます。
e-satis

43
また、isオペレーターをカスタマイズできない(ユーザー定義のクラスによってオーバーロードされる)ことを追加することもできます。
martineau

@studyこのメソッド__eq__(self)==、Pythonオブジェクトで使用した場合の処理方法を決定する特別な組み込みメソッドです。ここでは==、タイプのオブジェクトで使用されたときFooに常にtrueを返すようにオーバーライドしています。is演算子には同等のメソッドがないため、の動作をis同じ方法で変更することはできません。
ブレンダン

それは、fooクラスの定義にコンストラクター、つまりinit関数がないためですか?
学習

49

このオブジェクトのアイデンティティと同等性を読みたいと思うかもしれません。

ステートメント 'is'はオブジェクトの識別に使用され、オブジェクトが同じインスタンス(メモリ内の同じアドレス)を参照しているかどうかを確認します。

また、「==」ステートメントは等号(同じ値)を指します。


うーん、Pythonから外部関数を呼び出す方法に
Pat

試してみたところa=1;b=1;print(a is b) # Trueです。a is b2つの異なるオブジェクト(メモリ内の異なるアドレス)のように見えても、なぜ真であることがわかるのでしょうか?
Johnny Chiu

24

注意の言葉:

if foo:
  # do something

とまったく同じではありません

if x is not None:
  # do something

前者はブール値テストであり、さまざまなコンテキストでfalseと評価できます。空のコンテナー、ブール値など、ブール値のテストでfalseを表すものは多数あります。この状況でもfalseと評価されるものはありませんが、他のことも同様に評価されます。


12

(ob1 is ob2) に等しい (id(ob1) == id(ob2))


6
...(ob is ob2)はLOTが高速です。Timeitは、「(a is b)」はループごとに0.0365 usecであり、「(id(a)== id(b))」はループごとに0.153 usecであると述べています。4.2倍高速化!
AKX、

4
isバージョンは全く関数呼び出し、およびなしのpythonインタプリタ属性検索を必要としません。インタプリタは、ob1が実際にob2である場合、すぐに応答できます。
u0b34a0f6ae 2009年

17
いいえ、違います。{} is {}虚偽であるとid({}) == id({})することができ(及びある真CPythonの中で)。stackoverflow.com/questions/3877230を
Piotr Dobrogost

12

その理由foo is Noneは、独自の__eq__を定義し、オブジェクトをNoneに等しくなるように定義するオブジェクトを処理している可能性があるためです。そのため、foo is Noneそれが無事かどうかを確認する必要がある場合は、常に使用してくださいNone


8

もちろん、同一のオブジェクトは等しいため、違いはありません。ただし、PEP 8には、次のように使用する必要があることが明記されていますis

Noneなどのシングルトンとの比較は、is演算子またはis演算子ではなく、決して等価演算子で行う必要があります。


7

is同一性ではなく同一性をテストします。ステートメントのfoo is none場合、Pythonはオブジェクトのメモリアドレスを単に比較します。「同じオブジェクトに2つの名前がありますか?」という質問をしているということです。

==一方、__eq__()メソッドによって決定された等価性をテストします。それはアイデンティティを気にしません。

In [102]: x, y, z = 2, 2, 2.0

In [103]: id(x), id(y), id(z)
Out[103]: (38641984, 38641984, 48420880)

In [104]: x is y
Out[104]: True

In [105]: x == y
Out[105]: True

In [106]: x is z
Out[106]: False

In [107]: x == z
Out[107]: True

Noneシングルトン演算子です。だから、None is None常に真です。

In [101]: None is None
Out[101]: True

5

Noneの場合、等価(==)とアイデンティティ(is)の間に違いがあってはなりません。NoneTypeはおそらく、等しいかどうかのIDを返します。NoneはNoneTypeで作成できる唯一のインスタンスであるため(これは本当だと思います)、2つの操作は同じです。他のタイプの場合、これは常に当てはまるわけではありません。例えば:

list1 = [1, 2, 3]
list2 = [1, 2, 3]
if list1==list2: print "Equal"
if list1 is list2: print "Same"

リストにはデフォルトのIDの返りではない比較演算があるため、これは「等しい」を出力します。


5

@ ジェイソン

に沿ってもっと何かを使用することをお勧めします

if foo:
    #foo isn't None
else:
    #foo is None

fooが真にブール値(つまり0または1)を表していない限り、「if foo:」の使用は好きではありません。fooが文字列やオブジェクトなどの場合、「if foo:」は機能するかもしれませんが、私にとっては怠惰なショートカットのように見えます。xがNoneかどうかを確認している場合は、「xがNoneの場合:」と言います。


「if var」を使用して空の文字列/リストをチェックすることをお勧めします。ブール変換は明確に定義されており、パフォーマンスが向上するコードは少なくなります。たとえば、 "if len(mylist)== 0"を実行する理由はありません。
truppo 2010年

違う。foo = ""とします。次にif foofalseを返し、コメント#foo is Noneは間違っています。
blokeley

反対投票者への注意-私の回答は、削除された回答を引用しており、反対しています。私の回答のコードが気に入らない場合は、賛成投票する必要があります。:-)
Graeme Perrow、2011年

2

さらに詳細:

  1. このis句は、2つobjectのが同じメモリ位置にあるかどうかを実際にチェックします。つまり、両方が同じメモリ位置を指し、同じであるかどうかid

  2. 1の結果として、is字句的に表現された2つobjectのが同じ属性(attributes-of-attributes ...)を持っているかどうかを確認します

  3. 以下のようなプリミティブ型のインスタンス化はboolintstring(いくつかの例外を除いて)、NoneType同じ値を有することは、常に同じ記憶場所にあろう。

例えば

>>> int(1) is int(1)
True
>>> str("abcd") is str("abcd")
True
>>> bool(1) is bool(2)
True
>>> bool(0) is bool(0)
True
>>> bool(0)
False
>>> bool(1)
True

そしてNoneType、Pythonの「ルックアップ」テーブルにはそれ自体のインスタンスを1つしか含めることができないため、前者と後者は、コードを記述した開発者のプログラミングスタイルに近いものです(一貫性を保つため)。どちらかを選択してください。


2
誰もがこれを読んでいます:some_string is "bar"文字列を比較するためにこれまでに使用しないでください。そうするための単一の受け入れ可能な理由はありません、そしてあなたがそれを期待しないときそれは壊れます。CPythonが同じ内容の2つの不変オブジェクトを作成するのは愚かであることを知っているため、これが頻繁に機能するという事実は単純です。しかし、それはそれでも起こり得ます。
ThiefMaster 2013年

@ThiefMaster答えは誤解される傾向がありますか?しかし、それをもう一度読んだとき、はそれを見つけることができませんでした(「いくつかの例外」についての言及があります)。あなたの声明は文字列だけに当てはまり、そうintではありませんよね?
出血している指

実際にはそうではありませんが、あなたの回答にその例があるので、実際に使用するのは悪い考えであることをユーザーに警告するのは良い考えだと思いました。その行の後ろに「#cpython固有/保証なし」のようなものを追加するかもしれません...
ThiefMaster

1

NoneシングルトンであるJohn Machinの結論は、このコードによって補強された結論です。

>>> x = None
>>> y = None
>>> x == y
True
>>> x is y
True
>>> 

以来Noneシングルトンである、x == Nonex is None同じ結果を持っているでしょう。しかし、私の審美的な意見でx == Noneは、最高です。


2
この回答の最後の意見には同意しません。明示的にnoneと比較する場合、通常、問題のNoneオブジェクトは正確にオブジェクトであることが意図されています。比較するFalseと、他の値が真実であることと似ていることを除いて、他のコンテキストでNoneが使用されることはほとんどありません。そのような場合、次のようなことをするのがより慣用的ですif x: pass
SingleNegationElimination 2011年

0
a is b # returns true if they a and b are true alias
a == b # returns true if they are true alias or they have values that are deemed equivalence 


a = [1,3,4]
b = a[:] #creating copy of list
a is b # if gives false
False
a == b # gives true
True
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.