Pythonは比較演算子の左/右バージョンを提供していないため、どの関数を呼び出すかをどのように決定しますか?
class A(object):
def __eq__(self, other):
print "A __eq__ called"
return self.value == other
class B(object):
def __eq__(self, other):
print "B __eq__ called"
return self.value == other
>>> a = A()
>>> a.value = 3
>>> b = B()
>>> b.value = 4
>>> a == b
"A __eq__ called"
"B __eq__ called"
False
これは両方を呼び出すようです__eq__
機能。公式の決定木を探しているだけです。
a == b
式は、存在するため、A.__eq__
を呼び出します。そのコードにはself.value == other
が含まれます。 intは自身をBと比較する方法を知らないため、PythonはB.__eq__
を呼び出して、それをintと比較する方法を知っているかどうかを確認します。
比較する値を示すためにコードを修正する場合:
class A(object):
def __eq__(self, other):
print("A __eq__ called: %r == %r ?" % (self, other))
return self.value == other
class B(object):
def __eq__(self, other):
print("B __eq__ called: %r == %r ?" % (self, other))
return self.value == other
a = A()
a.value = 3
b = B()
b.value = 4
a == b
印刷されます:
A __eq__ called: <__main__.A object at 0x013BA070> == <__main__.B object at 0x013BA090> ?
B __eq__ called: <__main__.B object at 0x013BA090> == 3 ?
Python2.xはa == b
を検出すると、次のことを試みます。
type(b)
が新しいスタイルのクラスで、type(b)
がtype(a)
のサブクラスであり、type(b)
が__eq__
をオーバーライドした場合、結果b.__eq__(a)
です。type(a)
が__eq__
をオーバーライドした場合(つまり、type(a).__eq__
がobject.__eq__
ではない場合)、結果はa.__eq__(b)
になります。type(b)
が__eq__
をオーバーライドした場合、結果はb.__eq__(a)
になります。__cmp__
を探すプロセスを繰り返します。存在する場合、オブジェクトは、zero
を返す場合に等しいです。object.__eq__(a, b)
を呼び出します。これは、True
とa
が同じオブジェクトである場合、b
です。特別なメソッドのいずれかがNotImplemented
を返す場合、Pythonはメソッドが存在しないかのように動作します。
最後のステップに注意してください。a
もb
も==
をオーバーロードしない場合、a == b
はa is b
と同じです。