is はオブジェクトの比較で使うべし
Pythonでは、 if x is y
や if x == y
と書くことがあります。
その際に、is
と==
で迷ってしまう場合があります。
そこで、is
と==
の違いを以下にまとめました。
-
is
はオブジェクトの比較を行う(同一のオブジェクトかどうか) -
==
は値の比較を行う(同一の値かどうか)
※厳密には、オブジェクトの比較ではなく、「オブジェクトのIDの比較」であり、(結果的には)「アドレスの比較」となります。脚注1,2
ユースケース(isを使う場合)
x = <object A>
を定義していて、
if x is <object A>:
という条件式を書きたい場合が該当します。
もちろん、True/False比較のために
x = True
を定義して、
if x is True:
と書くことは、間違いではありませんが、この場合に関してはpythonic的に
if x:
と書くのが良いです。
→なぜ、 x is Trueでも問題ないかというと、boolクラスのTrue/Falseは、常にひとつだけしか存在しないように設計されているためです。
The values False and True will be singletons, like None.
引用元
PEP285
ユースケース(==を使う場合)
x = 1234
を定義していて、
if x == 1234:
という条件式を書きたい場合が該当します。
まとめ
is と == を混同せずに、しっかりと使い分けましょう。
脚注
脚注1
@7of9 さんよりコメント欄でご提示頂いた内容
id(object)
...
CPython implementation detail: This is the address of the object in memory.
がドキュメントで根拠となる部分です。
脚注2
@shiracamus さんよりコメント欄でご提示頂いた内容
CPythonのソースを調べてみました。
"is" は Is に置き換えられ、Is は PyCmp_IS に置き換えられ、PyCmp_IS は以下のようにアドレスを比較してました。
static PyObject *
cmp_outcome(int op, register PyObject *v, register PyObject *w)
{
int res = 0;
switch (op) {
case PyCmp_IS:
res = (v == w);
break;
case PyCmp_IS_NOT:
res = (v != w);
break;
のように、最終的にはアドレス比較を行っています。