128

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__関数を呼び出すようです。

公式の決定木を探しています。

4

3 に答える 3

152

存在するため、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 ?
于 2010-08-27T23:45:53.143 に答える
72

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)ます。
  • 上記のいずれにも当てはまらない場合、Pythonはを探してプロセスを繰り返します__cmp__。存在する場合、それが返す場合、オブジェクトは等しくなりますzero
  • 最後のフォールバックとして、Pythonはobject.__eq__(a, b)Trueiffabあり、同じオブジェクトであるを呼び出します。

特別なメソッドのいずれかが返される場合NotImplemented、Pythonはそのメソッドが存在しないかのように動作します。

最後のステップに注意してください。オーバーロードabオーバーロードもしない==場合a == bは、と同じa is bです。


https://eev.ee/blog/2012/03/24/python-faq-equality/から

于 2012-10-20T03:28:45.423 に答える