It seems to be a case of leaky abstraction, where the way python caches small objects becomes visible, another example:<p><pre><code>  &gt;&gt;&gt; a = &#x27;hn&#x27;
  &gt;&gt;&gt; a is &#x27;hn&#x27;
  True
  &gt;&gt;&gt; a = &#x27;&#x27;.join([&#x27;h&#x27;, &#x27;n&#x27;])
  &gt;&gt;&gt; a is &#x27;hn&#x27;
  False
  &gt;&gt;&gt; a
  &#x27;hn&#x27;
  &gt;&gt;&gt; a = &#x27;h&#x27; + &#x27;n&#x27;
  &gt;&gt;&gt; a is &#x27;hn&#x27;
  True
</code></pre>
Edit: found another interesting case<p><pre><code>  &gt;&gt;&gt; a = 1
  &gt;&gt;&gt; b = 1
  &gt;&gt;&gt; a is b
  True
  &gt;&gt;&gt; a = 500
  &gt;&gt;&gt; b = 500
  &gt;&gt;&gt; a is b
  False</code></pre>