'=='や 'is'を使って文字列を比較すると、異なる結果になることがあるのはなぜですか?

Pythonのプログラムで、2つの変数に 'public' という値が設定されているものがあります。条件式の中で、比較を var1 is var2 とすると失敗しますが、var1 == var2 とすると True を返します。

今度はPythonのインタープリタを開いて、同じ"is"の比較をすると成功します。

>>> s1 = 'public'
>>> s2 = 'public'
>>> s2 is s1
True

私はここで何を見逃しているのでしょうか?

ソリューション

isは同一性のテスト、==`は同一性のテストです。あなたのコードで起こることは、インタープリタでは次のようにエミュレートされます。

>>> a = 'pub'
>>> b = ''.join(['p', 'u', 'b'])
>>> a == b
True
>>> a is b
False

これでは、両者が同じではないのも当然ですよね?

言い換えればisid(a) == id(b)` のことです。

解説 (12)

isキーワードはオブジェクトの同一性のテストで、==`は値の比較です。

isを使用すると、オブジェクトが同じオブジェクトである場合に限り、結果が真となります。しかし、==`はオブジェクトの値が同じであればいつでも真となります。

解説 (0)

これは、 'is'の比較がfalseと評価された場合、2つの異なるオブジェクトが使用されているという事実と関係があると思います。これがtrueと評価された場合、内部的には全く同じオブジェクトを使用しており、新しいオブジェクトを作成していないことを意味します。おそらく、2秒ほどのほんのわずかな時間内に作成したため、大きな時間差がないために最適化され、同じオブジェクトを使用しているのだと思います。

これが、文字列オブジェクトの値を比較する際に、isではなく、等号演算子==を使うべき理由です。

>>> s = 'one'
>>> s2 = 'two'
>>> s is s2
False
>>> s2 = s2.replace('two', 'one')
>>> s2
'one'
>>> s2 is s
False
>>> 

この例では、以前に別の文字列オブジェクトである s2 を 'one'と等しくしましたが、s と同じオブジェクトではありません。これは、インタプリタが同じオブジェクトを使用しなかったためで、最初に 'one'に代入していなければ、同じオブジェクトになっていたはずです。

解説 (2)