Python
python3

Python で is と == の使いドコロを迷う人のためのTips

is はオブジェクトの比較で使うべし

Pythonでは、 if x is yif 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 さんよりコメント欄でご提示頂いた内容

https://docs.python.org/3.6/library/functions.html#id

id(object)
...
CPython implementation detail: This is the address of the object in memory.

がドキュメントで根拠となる部分です。

脚注2
@shiracamus さんよりコメント欄でご提示頂いた内容

CPythonのソースを調べてみました。
"is" は Is に置き換えられ、Is は PyCmp_IS に置き換えられ、PyCmp_IS は以下のようにアドレスを比較してました。

Python/ceval.c
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;

のように、最終的にはアドレス比較を行っています。