Pythonでは、情報を「オブジェクト」という単位で管理しています。
オブジェクトには、それぞれ固有の「オブジェクトID」が割り振られています。
同じものに見えるオブジェクトが本当に同じものなのか、id関数を使用して確認してみます。
同じものであるか
2つのオブジェクトがあるとして、これらが同じものであるか比較する方法としては、「==」と「is」があります。
等価「==」
「==」は、2つのオブジェクトが等価であるかを判定します。
これは、2つのオブジェクトが同じ値であれば、「オブジェクトID」が同じである必要はありません。
同一「is」
「is」は、2つのオブジェクトの「オブジェクトID」が同一であるか判定します。
「オブジェクトID」は、他のオブジェクトと重複しない一意の番号なので、「オブジェクトID」が同一であれば、同じオブジェクトだとわかります。
id関数 id(object)
id関数は、引数に「オブジェクト」を取ります。
返り値は、「オブジェクトID」です。
id関数を使用すると、オブジェクトIDを調べることができます。
「==」と「is」の違いをid関数で確認
整数の場合
整数のオブジェクトIDを確認します。
出力は、「#」で表記します。
整数「9」
id(9)
# 140713470760000
整数「10」
id(10)
# 140713470760032
整数「9」と整数「10」のオブジェクトIDが異なっていることが確認できました。
再度、整数「10」を確認します。
id(10)
# 140713470760032
整数「10」は、同じオブジェクトIDなので、同じオブジェクトです。
リストオブジェクトでは、別の結果になることを、後で確認します。
変数「a」に 、整数「10」を代入します。
a = 10
id(a)
# 140713470760032
変数「a」は、整数「10」と同じ「オブジェクトID」なので、同じオブジェクトです。
変数「b」に 、整数「10」を代入します。
b = 10
id(b)
# 140713470760032
変数「b」も、整数「10」と同じ「オブジェクトID」なので、同じオブジェクトです。
等価「==」と、同一「is」を使用して、確認します。
等価、同一の返り値はTrue、違うときの返り値はFalseです。
10 == 10
# True
整数「10」と 整数「10」 は、「等価」です。
10 is 10
# True
整数「10」と 整数「10」 は、「同一」です。
a == 10
# True
変数「a」と 整数「10」 は、「等価」です。
a is 10
# True
変数「a」と 整数「10」 は、「同一」です。
a == b
# True
変数「a」と変数「b」 は、「等価」です。
a is b
# True
変数「a」と変数「b」 は、「同一」です。
オブジェクトIDが同じ、整数「10」、変数「a」、変数「b」は、等価であり、同一であることがわかりました。
それでは、変数「b」に、整数「8」を代入してみます。
b = 8
print(b)
# 8
次に、変数「a」は変化したか、確認します。
print(a)
# 10
変数「a」には、変化はありません。
変数「b」のオブジェクトIDを確認します。
id(b)
# 140713470759968
変数「b」は、変数「a」とは別のオブジェクトであることがわかりました。
リストオブジェクトの場合
リストオブジェクトのオブジェクトIDを確認します。
出力は、「#」で表記します。
空のリストオブジェクト「[]」
id([])
# 3154278429384
再度、空のリストオブジェクト「[]」
id([])
# 3154278415688
リストオブジェクトのオブジェクトIDは、実行ごとに異なっています。
これは、別のオブジェクトが生成されていることを意味します。
変数「a」に 、空のリストオブジェクト「[]」を代入します。
a = []
id(a)
# 3154278562056
等価「==」と、同一「is」を使用して、確認します。
等価、同一の返り値はTrue、違うときの返り値はFalseです。
a == []
# True
変数「a」と空のリストオブジェクト「[]」は、「等価」です。
a is []
# False
変数「a」と空のリストオブジェクト「[]」は、「同一」ではありません。
それでは、変数「b」に、変数「a」を代入してみます。
b = a
id(b)
# 3154278562056
変数「b」と、変数「a」は同じ「オブジェクトID」なので、同じオブジェクトです。
変数 「b」に要素を追加してみます。
b.append(10)
print(b)
# [10]
空のリストオブジェクトに、要素として整数「10」が追加されました。
変数「b」の「オブジェクトID」を確認します。
id(b)
# 3154278562056
変数「b」の「オブジェクトID」は変化していません。
変数「b」は、値は変化しましたが、同じオブジェクトです。
空のリストオブジェクトと比較します。
b == []
# False
変数「a」と比較します。
a == b
# True
a is b
# True
変数「a」、変数「b」は、等価であり、同一であることがわかりました。
変数「a」を確認します。
print(a)
# [10]
変数「a」に、要素があります。
変数「a」には、空のリストオブジェクトを代入しただけで、要素は追加していません。
これは、変数「b」への変更が、変数「a」にも反映していることが原因です。
リストオブジェクトは、新しい変数に代入しても、もとの変数と同じオブジェクトです。
片方への変更は、もう片方にも反映します。
このように、Pythonのリストオブジェクトは、整数と動作が異なっています。
片方だけを変更したいときは、新しいオブジェクトを生成するcopy()メソッドを使用します。
copy()メソッド
変数「c」に、変数「a」のコピーを代入してみます。
c = a.copy()
id(c)
# 3154278597448
変数「c」と、変数「a」は異なる「オブジェクトID」なので、別のオブジェクトです。
変数「a」と比較します。
a == c
# True
a is c
# False
変数「a」、変数「c」は、等価ですが、同一ではないことがわかりました。
変数「c」を確認します。
print(c)
# [10]
変数 「c」に要素を追加してみます。
c.append(10)
print(c)
# [10, 10]
変数「c」に、整数「10」が追加されました。
変数「a」を確認します。
print(a)
# [10]
変数「c」への変更は、変数「a」には反映していません。
まとめ
- 等価「==」と、同一「is」 の違いがわかった
- id関数を使用して、オブジェクトIDを調べることができた
- copy()メソッドを使用して、オブジェクトのコピーができた
リストオブジェクトの場合、変数を別の変数に代入すると、思っていない結果になることがあります。
同じオブジェクトでよいときは、「=」で代入するだけですが、異なるオブジェクトがよいときは、copy()メソッドを使用するとよいでしょう。
2つのオブジェクトの比較は、等価「==」か、同一「is」で行いましょう。