インスタンスの同値を見る方法を考えてみた
python2.7にて試してみた。3.xではこの方法は使えないので注意。
勢いに任せて書いてみたが、もっと短くできそうな気もする。
こういうクラスを考えてみる
class Aa(object): def __init__(self, a, b): self.id = a self.name = b e = Aa(1, "akebono") r = Aa(2, "konishiki") t = Aa(1, "akebono")
という時に、 eと、rは等しいか?、当然、等しくない。
では、eとt は「等しい」のか?確かめてみるとこうなる
>>>e == r False >>>e == t False >>>e.id == t.id True >>>e.name == t.name True
e とrは別々のオブジェクトで、たまたま同じプロパティ(pythonでは広くアトリビュートという)を持っているに過ぎない。別々のオブジェクトだから「等しくない」。それは、オブジェクトを見てみればわかる。
>>> e <__main__.Aa object at 0x1004cbdd0> >>> t <__main__.Aa object at 0x1004cbe10> >>>
とはいえ、たくさんのインスタンスを作った時に比較できないのは不便なので、プロパティが同じ物を比較する方法を考えてみた。要は、javaでいうequalsの実装。
class Eq(object): def equals(self, other): b = [] for i in dir(self): if str(type(getattr(self, i))) != "<type 'instancemethod'>" and i.find("__") < 0: if getattr(self, i) == getattr(other, i): b.append(True) else: b.append(False) if len(b) == b.count(True): return True else: return False class Aa(Eq): def __init__(self, a, b): self.id = a self.name = b e = Aa(1, "akebono") r = Aa(2, "konishiki") t = Aa(1, "akebono") # 確認してみると >>> e.equals(r) False >>> e.equals(t) True >>> e.equals(e) True >>> e == t False
__のついたプロパティは比較から外している。
objectを継承しているので、__eq__をこの、equalsでオーバーライドすると、 == で比較することもできる。