Pythonのisと==は何が違うの!?




Pythonではオブジェクトを比較する方法として「is」や「==」やがありますが、どう違うのか見ていきたいと思います!

==とは!?

==」は、オブジェクトが「等価」であるか判定したい場合に使用します!問題なのは「等価」とはなんぞや!という事だと思います。

まず、簡単な比較で見てみましょう!

x = 1
y = 1
z = 0

print x == y # True
print x == z # False

x」と「y」は、同じ値なので「True」になりますが、「x」と「z」は、値が違うので「False」になります。

続いては、List系で見てみます!

vectorA = [0, 1, 0]
vectorB = [0, 1, 0]
vectorC = [1, 0, 0]
vectorD = (0, 1, 0)

print vectorA == vectorB # True
print vectorA == vectorC # False
print vectorA == vectorD # False

vectorA」と「vectorB」は、同じ値で同じ並び順なので「True」になりますが、「vectorA」と「vectorC」は、同じ値でも並び順が違うので「False」になります。

vectorA」と「vectorD」は、同じ値で同じ並び順ですが、「list型」と「tuple型」で型が違うので「False」になります。

更に、文字列系で見てみます!

nameA = 'pSphere'
nameB = u'pSphere'

print nameA == nameB # True

nameA 」と「nameB 」は、同じ文字で「str型」と「unicode型」になりますが「True」になります。

実は「等価」といっても、比較する物によって判定にバラツキがあります。

isとは!?

Pythonではオブジェクトを作成すると、オブジェクトごとに固有のIDを持つようになっていて、「is」はこのIDが同じであるかどうか判定する時に使用します!

オブジェクトのIDは、「id()」で調べることができます!

では、先程のlist型で「==」を使った比較は「True」の判定でしたが、「is」を使って比較してみてみます。

vectorA = [0, 1, 0]
vectorB = [0, 1, 0]
print id(vectorA), id(vectorB)# 1632865214280 1632865215048 ←実行するたびに変わります。
print vectorA is vectorB# False

vectorAとvectorBは、同じ値で同じ型ですが、「id」を見てみると異なるので「False」になります。

よく聞く「Noneはisを使え!」とは!?

どういうことや!?」とよく悩んでしまうのは、以下のケースのように、「==」でも「is」でも「True」になるからだと思います。

noneA = None
noneB = None
print noneA == noneA
print noneA is noneB

==」と「is」が「True」になる理由は、「None」は何個作っても「すべて同じIDになる」世界に1だけのオブジェクトだからです。これを「シングルトン」といいます。Mayaで例えると、「インスタンスコピー」のようなもです。

Noneは、必ず「」も「ID」も同じなので「==」と「is」が「True」になりますが、なぜ「is」が推薦されるかというと、、、

==」の判定は、「__eq__」をオーバーライドできるので確実性がない

これを体験していただく為に、「==」の判定をいじったオブジェクトと比較してみます。

class Vector(object):
	def __eq__(self, other):
		return True
		
objectA = Vector()
objectB = None

print objectA == objectB# True
print objectA is objectB# False

objectA」と「objectB」を「==」で比較すると、全然違うはずなのに「True」となってしまいます。これはクラス「Vector」で「__eq__」をオーバーライドして「==」の判定を必ず「True」にしたからです。

Noneと比較で「is」を使えば、「判定が確実」ということになります!(`・ω・´)ゞ