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が同じであるかどうか判定する時に使用します!
では、先程の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」を使えば、「判定が確実」ということになります!(`・ω・´)ゞ