Pythonのisって何、==と違うの?

Pythonでたまに見かけるisって何ですか? ==とはどう違うんですか?

==の働き

==はオブジェクト同士が等価であるかを判定する演算子です。
等価というのは同じ意味を持つかどうかというのを指します。

list_1 = [1,2,3]
list_2_= [1,2,3]
list_3 = [1,3,2]

tuple_1 = (1,2,3)
str_1 = "e-tec-memo"

print(list_1 == list_2)
print(list_1 == list_3)
print("=====")
print(list_1 == tuple_1)
print(str_1 == "e-tec-memo")

実行結果

True
False
=====
False
True

リストの場合list_1とlist_2は別のオブジェクトですが、同じ値を同じ順番で保持しているため、==の結果はTrue、つまり等価となります。

一方、list_1とlist_3は同じ値を保持してはいますが、保持している順番が違うため、==での比較はFalseになります。
また、list_1とtuple_1は同じ値を同じ順番で保持していますが、クラスが異なるためFalseになります。
文字列の比較は同じ文字列かどうかの比較なのでわかりやすいと思います。
このように等価といってもリストやタプル、文字列によって等価であるかどうかの判定にはある程度の幅があります。

isの働き

pythonではオブジェクトが生成されるとそのオブジェクトは、他のオブジェクトと重複することのないユニークな番号を割り当てられます。

このユニークな番号は組み込み関数のidで確認できます。

isはその番号を比較し、同一のオブジェクトかどうかを判定します。

list_1 = [1,2,3]
list_2_= [1,2,3]

print(list_1 == list_2)
print(list_1 is list_2)
print("=====")
print(id(list_1) == id(list_1))
print(list_1 is list_1)

実行結果

True
False
=====
True
True

また以下のように実行すると結果が少し変わります。

list_1 = [1,2,3]
list_2 = list_1

print(list_1 == list_2)
print(list_1 is list_2)
print("=====")
print(id(list_1) == id(list_1))
print(list_1 is list_1)

実行結果

True
True
=====
True
True

list_2にlist_1を代入しました。
すると、list_1islist_2がTrueになりました。

この結果は、list_1とlist_2は同じオブジェクトということなので、リストの代入はコピーではなく参照渡しであるということがわかります。

つまりこれは、list_1の値を書き換えるとlist_2の値も書き換わるということを意味します。

おまけ

PythonのNoneはシングルトンなのでNoneの比較をするときは==を使って比較するよりもisを使って比較するほうが好ましいです。

何故なら、Noneの==による比較は内部でisを呼び出して比較しているので関数呼び出しのコスト分若干早く動作するからです。

まとめ

isは同一のオブジェクトかどうかを判定する演算子。
==は同じ値かを判断する演算子。