Pythonのイコール2つ(==)とisの違いや使い分けについて解説する

スポンサーリンク

演算子 ==is はどちらも Python で非常によく似たタスクを実行しますが、互いに非常に異なっており、Python がどのように変数をメモリに格納するかという非常に興味深い概念を扱います。

スポンサーリンク

== と is の違いを理解する

簡単に言うと

  • == は二つのオペランドの値をチェックし、同じであれば True を、そうでなければ False を返します。
  • is は 2 つのオペランドのオブジェクト ID をチェックして、同じなら True を返します。

しかし、オブジェクト ID とは何だろうか?すべてのオブジェクトはメモリ上で ID を割り当てられ、2 つの変数は同じオブジェクトを指すことができるので、同じオブジェクト ID を持つことになります。

リストを使って、その違いを見てみましょう。

lst1 = [1,2,3]
lst2 = [1,2,3]
print(lst1 == lst2)
print(lst1 is lst2)
 
lst2 = lst1
print()
print(lst1 is lst2)

結果は以下の通りです。

出力:“`
True
False

True

上記の場合、最初はメモリ上に2つのリストが存在しますが、両者は全く同じ値を保持しています。

* `==` は値を比較するので、この演算は `True` を返します。
* しかし、`is`は同じオブジェクトを指しているかどうかをチェックし、これらのリストは実際には異なるオブジェクトであるため、`False`を返します。
* この後、 `lst2` を `lst1` と等しくすると、 `lst2` は `lst1` が指している場所を指すようになり、 `is` は `True` を返します。

これらのことは、整数の場合と大きく異なります。これを理解するためには、オブジェクトがどのようにメモリに格納されるかを知る必要があります。



## Pythonのメモリ割り当て

このチュートリアルを進めるには、Pythonのオブジェクトのメモリ割り当てを理解する必要があります。

例を見てみましょう。

<div class="wp-block-syntaxhighlighter-code"><div><div class="syntaxhighlighter nogutter python" id="highlighter_551844"><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">number </code><code class="python keyword">=</code> <code class="python value">10</code></div></div></td></tr></tbody></table></div></div></div>

ここで、`number`が10という値を持っていることはわかりましたが、それはどのようにメモリに格納されているのでしょうか?Pythonでは、すべてのオブジェクトはメモリ内に4つの部分を持っています。

1. 1. サイズ - すべてのオブジェクトに対して、4バイトが予約され、オブジェクトのサイズが格納されます。
2. 2. 参照回数 - すべてのオブジェクトについて、8バイトが予約されており、このオブジェクトを指している変数の数を保持しています。また、これらのオブジェクトはすべて、このオブジェクトのオブジェクトIDを持ちます。
3. 3. オブジェクトタイプ - すべてのオブジェクトについて、8バイトが予約されており、どのタイプのオブジェクトであるかを示す情報が保持されます。
4. 4. オブジェクトの値 - すべてのオブジェクトに対して、さらに8バイトが予約されており、オブジェクトの実際の値が格納されています。

さて、上記のリストの中で、今回の議論で重要なのは、オブジェクトの値と参照カウントです。

つまり、`number = 10`の場合、オブジェクトの値が10で参照カウントが1であるオブジェクトがメモリ上に存在し、1つの変数がそれを指していることになります(この場合、`number`です)。

ここで、別の変数をこのように宣言するとしよう。

<div class="wp-block-syntaxhighlighter-code"><div><div class="syntaxhighlighter nogutter python" id="highlighter_814341"><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">number_2 </code><code class="python keyword">=</code> <code class="python plain">number</code></div><div class="line number2 index1 alt1"><code class="python functions">print</code><code class="python plain">(number </code><code class="python keyword">=</code><code class="python keyword">=</code> <code class="python plain">number_2)</code></div><div class="line number3 index2 alt2"><code class="python functions">print</code><code class="python plain">(number </code><code class="python keyword">is</code> <code class="python plain">number_2)</code></div></div></td></tr></tbody></table></div></div></div>

ここで、メモリ内で非常に興味深いことが起こります。新しいオブジェクトは作成されず、 `number_2` も `number` が指している場所を指すようになり、オブジェクトの参照カウントが 2 に増加します。

その結果、`number` と `number_2` は同じオブジェクト ID を持つことになり、次のような出力になります。

True
True

しかし、このようにするとどうでしょう?

<div class="wp-block-syntaxhighlighter-code"><div><div class="syntaxhighlighter nogutter python" id="highlighter_415598"><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">num1 </code><code class="python keyword">=</code> <code class="python value">10</code></div><div class="line number2 index1 alt1"><code class="python plain">num2 </code><code class="python keyword">=</code> <code class="python value">10</code></div><div class="line number3 index2 alt2"><code class="python functions">print</code><code class="python plain">(num1 </code><code class="python keyword">=</code><code class="python keyword">=</code> <code class="python plain">num2)</code></div><div class="line number4 index3 alt1"><code class="python functions">print</code><code class="python plain">(num1 </code><code class="python keyword">is</code> <code class="python plain">num2)</code></div></div></td></tr></tbody></table></div></div></div>

上の例では、出力は次のようになります。

True
True

## -5 から 256 までの特別な数

Pythonは-5から256までの整数を一般的に使われる整数とみなしています。そのため、これらの整数を表すオブジェクトは常に定義済みで、メモリからこれらのオブジェクトを削除することはできません。

そのため、Pythonのコードの最初では、これらのオブジェクトはすべて参照カウントが0ですが、もし変数に-5から256(を含む)までの値を持たせると、新しいオブジェクトは作られず、すべての変数はすでに存在するオブジェクトを指すようになるだけです。

つまり、上記のコードでは、10を表すオブジェクトはすでにメモリ上に存在し、最初の2行はその同じオブジェクトを指す変数を作成しているだけです。

そこで、次のようなコードになります。

<div class="wp-block-syntaxhighlighter-code"><div><div class="syntaxhighlighter nogutter python" id="highlighter_796018"><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td class="code"><div class="container"><div class="line number1 index0 alt2"><code class="python plain">num1 </code><code class="python keyword">=</code> <code class="python value">257</code></div><div class="line number2 index1 alt1"><code class="python plain">num2 </code><code class="python keyword">=</code> <code class="python value">257</code></div><div class="line number3 index2 alt2"><code class="python functions">print</code><code class="python plain">(num1 </code><code class="python keyword">=</code><code class="python keyword">=</code> <code class="python plain">num2)</code></div><div class="line number4 index3 alt1"><code class="python functions">print</code><code class="python plain">(num1 </code><code class="python keyword">is</code> <code class="python plain">num2)</code></div></div></td></tr></tbody></table></div></div></div>

出力は次のようになります。

True
False
``
これは、pythonがその範囲外の整数を宣言するたびに新しいインスタンスを作成するためです。もし、
num2 = num1とした場合、num1` の値がどうであれ、両者は同じオブジェクトを指すことに注意してください。

まとめ

この記事では、==is の違い、そして is が 2 つの変数が同じメモリ位置を指しているかどうかを調べるのに便利であることを確認しました。

また、-5 から 256 までの整数がよく使われると考えられているため、メモリにキャッシュされ('a''b' といった文字も同様にキャッシュされます)、この範囲内で同じ値を持つ 2 つの変数が同じオブジェクトを指していることを確認できました。

タイトルとURLをコピーしました